3

C++03 標準 (5.3.4/7) によると:

direct-new-declarator の式の値が 0 の場合、要素のない配列を割り当てるために割り当て関数が呼び出されます。

私の読みでは、これは、このコードが合法であり、特定の効果があることを意味します。

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
    A() : a_(++aa_) {};
    int a_;
    static int aa_;
};
int A::aa_ = 0;

int main()
{
    A* a = new A[0];
    // cout << "A" << a->a_ << endl; // <-- this would be undefined behavior
}

このコードをデバッガーで実行すると、Aのコンストラクターが呼び出されないことがわかります。 newスローせず、null 以外の明らかに有効なポインターを返します。ただし、 at の値a->a_は初期化されていないメモリです。

質問:

  1. 上記のコードでは、a実際には何を指しているでしょうか?
  2. 「要素のない配列を割り当てる」とはどういう意味ですか?
  3. 要素がゼロの配列を割り当てることは、実際にどのような用途に使用されますか?
4

3 に答える 3

5

上記のコードで、a は実際には何を指しているでしょうか?

ゼロ要素配列を指します。

「要素のない配列を割り当てる」とはどういう意味ですか?

これは、有効な配列を取得することを意味しますが、サイズはゼロです。値が存在しないため、値にアクセスすることはできませんが、サイズがゼロの各配列が異なる場所を指しているため、イテレータを past-the-end にすることもできます&a[0]。したがって、他のすべての配列を使用するのと同じように使用できます。

要素がゼロの配列を割り当てることは、実際にどのような用途に使用されますか?

n = 0を呼び出すたびにチェックする手間を省くだけですnew。静的配列には定数式から得られる静的サイズがあるため、サイズがゼロの静的配列は不正であることに注意してください。さらに、イテレータのペアを取る標準アルゴリズムまたはカスタム アルゴリズムを呼び出すことができます。

于 2012-06-17T19:53:18.100 に答える
4

あなたのaポイントは(有効に)ゼロ連続要素であり、ゼロ要素が構築されています。式a->a_は と同じでa[0].a_、範囲外であり、したがって未定義の動作です。

さらに、「値は初期化されていないメモリです」というステートメントa->a_は意味がないようです。値は値であり、メモリはメモリです-値はメモリではありませ。を決して逆参照してはならないことはすでに確立しているので、ポイントaする変数の任意の種類の値を要求することは無意味です。aa

delete[] a;割り当てられたメモリを解放し、すべてのゼロ オブジェクトを破棄すると言うことは、依然として完全に有効です (そして予想される?!) 。

(C のmalloc関数は引数を付けて呼び出すこともできますが0、その戻り値については、それ以外の保証がないことに注意してくださいfree。C++ では、実際には、毎回個別null 以外の::operator new[]値を返す必要があります (値を再利用することを条件として、に渡されました)。::operator delete[]

于 2012-06-17T19:51:46.343 に答える
3

new whatever[0]つまり、現在割り当てられている他のオブジェクトとは異なる有効なアドレスが返されますが、逆参照することはできません。

典型的な用途は、さまざまなサイズの配列を割り当てるコードで使用されるため、正の数の要素を持つ配列を持つ場合もあれば、要素がゼロの配列を持つ場合もあります。逆参照することはできませんが、(たとえば) null ポインターの代わりに「通常の」(有効な) ポインターを使用すると、かなりのコードを単純化できます。

ほんの一例として、配列の先頭のアドレスと、配列の末尾の 1 つ先のアドレスを格納する典型的なケースを考えてみましょう (そして、一方から他方へトラバースするループがあります)。ヌル ポインターでは、そのような算術演算を行うことはできません。そのため、ワンパス ザ エンド ポインターを処理するものはすべて、ヌル ポインター用の特別なケースが必要になります。逆参照できない有効な非 null ポインターの場合でも、特別なケースがなくても、開始アドレスと終了アドレスを形成できます。null 以外のポインターに対してのみループを実行する特別なケースのコードの代わりに、配列が空の場合にゼロ反復を実行する通常のループを記述します。

于 2012-06-18T01:18:29.780 に答える