“ int * ptr = int()”值初始化如何合法?


86

以下代码(从此处获取):

int* ptr = int();

在Visual C ++中进行编译,并对值进行初始化。

那怎么可能?我的意思是int()产生一个类型的对象,int我不能将分配int给指针。

上面的代码如何不违法?


不是答案,而是很好的问题!我从未见过这样的事情。
乔什

6
由于基元在C ++中具有“构造函数”,因此会int()产生值的构造值int(我认为这是C ++ 03指定的值),默认值int0。这等效于int *ptr = 0;
wkl 2011年

7
@EmanuelEy:否,任何零值整数常量都可以用作空指针常量,而不管指针的实际实现方式如何。
Mike Seymour

1
@MooingDuck:我没有说NULL可能是非零值。我说过,它可以是任何零值整数常量(包括int())。
Mike Seymour

5
@DanielPryden这是我以前没有意识到的“对象”一词的使用。
蓬松的

Answers:


110

int()是值为0的常量表达式,因此它是产生空指针常量的有效方法。最终,这只是一种稍微不同的说法int *ptr = NULL;


3
+1,常量表达式位很重要,在排名靠前的2个答案中都没有。
DavidRodríguez-dribeas 2011年

C ++ 0x可以解决吗?
尼尔·G

@NeilG:尽管现在也有一个nullptr,您可以在C ++ 11中使用它代替0NULL在新代码中使用。
杰里·科芬

2
@Nils:代码清晰,并通过代码声明您的意图。当然,在C ++ 11中,现在您想使用nullptr,因为它还将多余的编译时检查的好处丢给了混合对象。
Jamin Gray

3
@Nils,因为很明显它0可能表示空指针常量或数字0,而nullptr显然是空指针常量。此外,正如Jamin所说,它还具有“额外的编译时检查”功能。在键入之前,请尝试思考。
Miles Rout 2014年

35

因为int()产量0,这是可以互换的NULLNULL本身被定义为0,与C的NULL这是(void *) 0

请注意,这将是一个错误:

int* ptr = int(5);

并且仍然可以使用:

int* ptr = int(0);

0是一个特殊的常量值,因此可以将其视为指针值。产生0诸如的常量表达式1 - 1也可以与空指针常量一起使用。


1
还要注意,C的NULL也不一定(void *)0。它只是一个定义为“值为0的整数常量表达式,或此类转换为void *的表达式”的实现。
杰里·科芬

@JerryCoffin我从未使用过定义NULL(void*)0;的C编译器。总是0(或者也许0L)。(但是,当C90(void*)0在C中成为合法代码时,我已经在使用C ++。)
James Kanze 2011年

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。
大卫·罗德里格斯(DavidRodríguez)-dribeas 2011年

5
0是特殊文字”-仅因为它是一个常量表达式,并且具有特殊值0。(1-1)同样特殊,它也是一个空指针常量,因此也是int()0作为文字的事实足以成为常量表达式,但不是必需的条件。诸如之类的东西strlen(""),尽管也具有特殊的值,但它0不是常量表达式,因此也不是空指针常量。
史蒂夫·杰索普

@SteveJessop:我同意更正,实际上是关于常量值0,而不是0字面量。
Blagovest Buyukliev 2011年

18

表达式的结果int()为一个常量的默认初始化整数,该整数值为0。该值很特殊:它用于初始化一个指向NULL状态的指针。


2
这遗漏了Jerry的答案中的一个非常重要的细节:仅表达式产生的值为0是不够的,但是它还必须是一个常量表达式。作为反例,使用时int f() { return 0; },表达式f()的值为0,但不能用于初始化指针。
DavidRodríguez-dribeas 2011年

@DavidRodríguez-dribeas,我急于以最简单的方式提出答案,我将这一部分省略。我希望现在可以接受。
Mark Ransom

13

从n3290(C ++ 03使用类似的文本)开始,有4.10指针转换[conv.ptr]第1段(重点是我的):

1空指针常量是整数类型的整数常量表达式(5.19)prvalue,其值为零或std :: nullptr_t类型的prvalue。空指针常量可以转换为指针类型。结果是该类型的空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开。这种转换称为空指针转换。[...]

int()是这样的整数类型的整数常量表达式prvalue,其结果为零(这是一个满口!),因此可用于初始化指针类型。如您所见,0并不是唯一的特殊情况的整数表达式。


4

好吧,int不是对象。

我相信这里发生的事情是你告诉int *指向由int()确定的某些内存地址

因此,如果int()创建0,则int *将指向内存地址0


1
int()最肯定一个对象。
Lightness Races in Orbit

@Tomalak:我认为不是。这是一个临时的非类类型,我认为我说对了,就C ++标准而言,它们不是对象。不过,这有点奇怪,有关“临时对象”的部分开始时仅仔细地讨论了类类型的临时对象,但随后又讨论了绑定引用,当然您可以将引用绑定到int()。定义int i;毫无疑问i是一个对象。
史蒂夫·杰索普

@Steve:我只希望就此进行辩论,因为“对象”是C ++中的存储区域,临时对象实际上没有存储,对吗?1.8 / 1并未明确列出临时人员,但感觉似乎是有意将它们包括在内。
Lightness Races in Orbit

1
@Tomalak:是的,确实,非类类型的临时对象不需要存储,除非您进行引用。不过没关系,这无关紧要。语句“ well int不是对象”仅因int是类型而不是对象而成立。无论是int()产生一个对象或只是一个右值不会影响任何人在其他地方也说。
史蒂夫·杰索普

@Steve:这是不容小eb的:)
赛将于
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.