「int * ptr = int()」値の初期化はどのように違法ではありませんか?


86

次のコード(ここから取得):

int* ptr = int();

Visual C ++でコンパイルし、ポインタを値初期化します。

そんなことがあるものか?I平均int()利回り型のオブジェクトintと私は割り当てることができませんintポインタに。

上記のコードはどのように違法ではありませんか?


答えではありませんが、すばらしい質問です。私はそのようなことを見たことがありません。
Josh

6
プリミティブにはC ++で「コンストラクター」があるため、の構築int()int(C ++ 03で指定されたものだと思います)を生成し、のデフォルト値はintです0。これは、int *ptr = 0;
wkl 2011年

7
@EmanuelEy:いいえ、ポインターが実際にどのように実装されているかに関係なく、ゼロ値の整数定数をnullポインター定数として使用できます。
マイクシーモア

1
@MooingDuck:NULLゼロ以外の値になる可能性があるとは言いませんでした。私はそれが任意のゼロ値の整数定数(を含むint())である可能性があると言いました。
マイクシーモア

5
@DanielPrydenこれは、私が以前は気づかなかった「オブジェクト」という言葉の使用です。
ふわふわ

回答:


110

int()は値0の定数式であるため、nullポインタ定数を生成する有効な方法です。結局のところ、それはほんの少し異なる言い方ですint *ptr = NULL;


3
+1、定数式ビットは重要であり、上位2つの賛成回答から欠落しています。
デビッドロドリゲス-ドリビア2011年

これはC ++ 0xでなくなりますか?
ニールG

@NeilG:これはC ++ 11でも同じnullptrですが、新しいコードの代わりに、0またはNULL新しいコードで使用できる、もあります。
ジェリーコフィン

2
@Nils:コードを明確にし、コードを通じて意図を宣言します。もちろん、C ++ 11では、nullptrを使用する必要があります。これは、追加のコンパイル時チェックの利点もミックスに組み込まれるためです。
ジャミング

3
@Nilsは、明らかに0nullポインター定数または数値0を意味する可能性があるのに対し、明らかにnullポインター定数を意味するためnullptrです。さらに、Jaminが言ったように、「追加のコンパイル時チェック」もあります。入力する前に考えてみてください。
マイルルート2014年

35

int()0、と交換可能なを生成するためNULLです。NULLである0CNULLとは異なり、それ自体はとして定義され(void *) 0ます。

これはエラーになることに注意してください。

int* ptr = int(5);

そしてこれはまだ機能します:

int* ptr = int(0);

0は特別な定数値であるため、ポインタ値として扱うことができます。を生成する定数式0など1 - 1は、nullポインタ定数としても使用できます。


1
また、CのNULLも必ずしもそうではないことに注意してください(void *)0。これは、「値0の整数定数式、またはvoid *型にキャストされたそのような式」で定義された実装です。
ジェリーコフィン

@JerryCoffin ;NULLとして定義されたCコンパイラを使用したことはありません(void*)0。それはいつも0(または多分0L)でした。(しかし、C90が(void*)0Cで合法化されるまでに、私はすでにC ++を使用していました。)
James Kanze

1
@JamesKanze:ubuntu 11.04と独自のLinuxフレーバーでは、libio.hには次#if !defined(__cplusplus) \n #define NULL ((void*)0) \n #else \n #define NULL (0)のものが含まれています。ubuntuのgccの現在のバージョンは4.5で、システムでは4.0です。
デビッドロドリゲス-ドリビア2011年

5
0は特別なリテラルです」-定数式であり、特別な値0を持っているという理由だけで、(1-1)同様に特別であり、nullポインタ定数でもありますint()0リテラルであるという事実は十分ですが、定数式であるための必要条件ではありません。のようなものstrlen("")は、特別な値もあります0が、定数式ではないため、nullポインター定数ではありません。
スティーブジェソップ2011年

@SteveJessop:修正については同意します。実際0には、0リテラルではなく定数値についてです。
Blagovest Buyukliev 2011年

18

この式int()は、デフォルトで初期化された定数の整数、つまり値0に評価されます。この値は特別です。これは、NULL状態へのポインターを初期化するために使用されます。


2
これには、ジェリーの答えにある非常に重要な詳細が欠けています。式が値0を生成するだけでは不十分ですが、定数式でなければなりません。反例の場合、を使用するint f() { return 0; }と、式f()は値0を生成しますが、ポインターの初期化には使用できません。
デビッドロドリゲス-ドリビア2011年

@DavidRodríguez-dribeas、急いで答えをできるだけ簡単な言葉で提示するために、その部分を省略しました。私はそれが今受け入れられることを願っています。
マークランサム

13

n3290(C ++ 03は同様のテキストを使用)から、4.10ポインター変換[conv.ptr]段落1(強調は私のものです):

1 nullポインター定数は、整数型の整数型のprvalue(5.19)であり、ゼロまたはstd :: nullptr_t型のprvalueと評価されます。nullポインター定数は、ポインター型に変換できます。結果はそのタイプのnullポインター値であり、オブジェクトポインターまたは関数ポインタータイプの他のすべての値と区別できます。このような変換は、ヌルポインタ変換と呼ばれます。[...]

int()は、ゼロと評価される整数型の整数型の整数型式prvalueであり(これは一口です!)、したがって、ポインター型を初期化するために使用できます。ご覧のとおり、0特殊な場合の積分式はこれだけではありません。


4

まあintはオブジェクトではありません。

ここで起こっていることは、int()によって決定されるメモリアドレスを指すようにint *に指示していることだと思います。

したがって、int()が0を作成する場合、int *はメモリアドレス0を指します。


1
int()最も確かにあるオブジェクトが。
軌道上でのライトネスレース

@Tomalak:そうではないと思います。これは非クラス型の一時的なものであり、C ++標準に関する限り、これらはオブジェクトではないと言っているのは正しいと思います。少し奇妙なことですが、「一時オブジェクト」のセクションでは、クラスタイプの一時オブジェクトについてのみ注意深く説明しますが、後で参照のバインドについて説明しint()ます。もちろん、への参照をバインドできます。定義するとint i;、質問iはありませんが、オブジェクトです。
スティーブジェソップ2011年

@Steve:「オブジェクト」はC ++のストレージの領域であり、一時的なものには実際にはストレージがないという点で、これについての議論を期待するだけですよね?1.8 / 1は一時的なものを明示的にリストしていませんが、それらを含める意図があるように感じます。
軌道上でのライトネスレース

1
@Tomalak:はい、確かに、非クラス型の一時的なものは、参照しない限りストレージを必要としません。でも気にしないでください、それはそれほど重要ではありません。「wellintはオブジェクトではありません」というステートメントintは、がタイプであり、オブジェクトではないためにのみ当てはまります。int()オブジェクトを生成するか、単に右辺値を生成するかは、他の人が言ったことには影響しません。
スティーブジェソップ

@スティーブ:それだけは議論の余地がありません:)
軌道での
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.