要素数0の配列を
int array[0];
のように宣言すると,もちろんコンパイルエラーになります.
しかし,
int *p = new int [0];
p[0] = 10;
cout << p[0] << endl;
などとすると実行できてしまいます.これはどういう仕組みなのでしょうか.
また,この使用法は問題ないのでしょうか.
要素数0の配列
Re: 要素数0の配列
int arrはint *(arr+i)の糖衣構文です。
わざわざその書き方をしたい理由はさっぱりわかりませんが、
せめてdeleteするなりスマートポインタを使うなりして下さい。
#include <iostream>
int main()
{
int *p = new int [0];
p[0] = 10;
std::cout << p[0] << std::endl;
int *q = new int;
q[0] = 20;
std::cout << q[0] << std::endl;
int *r = new int( 30 );
std::cout << r[0] << std::endl;
delete p;
delete q;
delete r;
}
せめてdeleteするなりスマートポインタを使うなりして下さい。
Re: 要素数0の配列
最初の文は要素数0の int 領域を確保して、そのアドレスを返します。
つまりメモリアドレスは返ってくるが、その領域は使えない(使ってはいけない)
2、3番目の文は、その使ってはいけない領域にデータを書込み、読み出しています。
動作したのは、たまたまです。運よくそのアドレスのデータは他に使用されていなかった為でしょう。
もちろん大問題です。こんな使い方を決して行ってはいけません。dom さんが書きました:また,この使用法は問題ないのでしょうか.
Re: 要素数0の配列
> これはどういう仕組みなのでしょうか.
簡単に言えば、仕様です。
C言語からある通常の配列は、要素数 0 個の配列を許可していません。
しかし、C++ の new を使った配列の動的確保での要素数は 0 個を許可しています。
> また,この使用法は問題ないのでしょうか.
問題があります。
p[0] にアクセスする必要があるなら少なくとも 1 個の要素が必要です。
要素数が 0 ということは、一切の要素が存在していないということなので、要素へのアクセスは決してできません。 と、1以上を指定するべきです。
また、new int[] で確保した配列は、delete[] によって解放する必要があります。
実際は、int 等の組み込み型であれば単に delete しても問題無く動作すると思いますが、仕様的には未定義動作です。
簡単に言えば、仕様です。
C言語からある通常の配列は、要素数 0 個の配列を許可していません。
しかし、C++ の new を使った配列の動的確保での要素数は 0 個を許可しています。
> また,この使用法は問題ないのでしょうか.
問題があります。
p[0] にアクセスする必要があるなら少なくとも 1 個の要素が必要です。
要素数が 0 ということは、一切の要素が存在していないということなので、要素へのアクセスは決してできません。 と、1以上を指定するべきです。
また、new int[] で確保した配列は、delete[] によって解放する必要があります。
実際は、int 等の組み込み型であれば単に delete しても問題無く動作すると思いますが、仕様的には未定義動作です。
Re: 要素数0の配列
ありがとうございます.やはりこのような使い方はダメなんですね.
質問の理由ですが,
コンストラクタで引数に応じた要素数の配列を生成し,デストラクタでそれを開放する
ようなことをしていたのですが,要素数が0でも問題なさそうに動作したので気になって質問してみました.
質問の理由ですが,
コンストラクタで引数に応じた要素数の配列を生成し,デストラクタでそれを開放する
ようなことをしていたのですが,要素数が0でも問題なさそうに動作したので気になって質問してみました.
Re: 要素数0の配列
> やはりこのような使い方はダメなんですね.
このような、がどういった使い方によりますね。
例えば、以下のように 0 個の要素を確保するのは問題ありません
つまり、0 個の要素を new しても、p[0] や *p といった操作で実際に要素にアクセスしなければ問題ないのです。
この例では ar.length() が 0 で、for 文の中身が実行されないため、正しく動作します。
このような、がどういった使い方によりますね。
例えば、以下のように 0 個の要素を確保するのは問題ありません
class Array {
int* p;
int size;
public:
Array(int size) : p(new int[size]), size(size) { }
~Array() { delete[] p; }
int length() const { return size; }
int& operator[](int n) const { return p[n]; }
// その他は省略
};
int main() {
Array ar(0);
for (int i = 0; i < ar.length(); i++) {
ar[i] = 10; // ここは決して実行されない
}
}
この例では ar.length() が 0 で、for 文の中身が実行されないため、正しく動作します。