【问题标题】:How is "int* ptr = int()" value initialization not illegal?“int* ptr = int()”值初始化如何不非法?
【发布时间】:2011-12-25 10:58:03
【问题描述】:

以下代码(取自from here):

int* ptr = int();

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

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

上面的代码怎么不违法?

【问题讨论】:

  • 不是一个答案,而是一个好问题!我从来没有见过这样的事情。
  • 由于原语在 C++ 中有一个“构造函数”,int() 产生 int 的值构造值(我认为这是 C++03 指定的东西)和 @987654328 的默认值@ 是 0。这相当于int *ptr = 0;
  • @EmanuelEy:不,任何零值整数常量都可以用作空指针常量,无论指针实际是如何实现的。
  • @MooingDuck:我没有说NULL 可能是一个非零值。我说它可以是任何零值整数常量(包括int())。
  • @DanielPryden 这是我以前不知道的“对象”这个词的用法。

标签: c++ visual-c++ pointers initialization built-in-types


【解决方案1】:

int() 是一个值为 0 的常量表达式,因此它是生成空指针常量的有效方法。归根结底,这只是int *ptr = NULL;的说法略有不同

【讨论】:

  • +1,constant expression 位很重要,并且在前 2 名被投票的答案中缺失。
  • 这会随着 C++0x 消失吗?
  • @NeilG:这在 C++11 中保持不变,尽管现在还有一个 nullptr,您可以在新代码中使用它来代替 0NULL。跨度>
  • @Nils:代码清晰并通过代码声明您的意图。当然,对于 C++11,现在您想使用 nullptr,因为它还会将额外编译时检查的好处混在一起。
  • @Nils 因为很明显0 可能表示一个空指针常量或数字0,而nullptr 显然是一个空指针常量。此外,正如 Jamin 所说,它还有“额外的编译时检查”。打字前一定要三思。
【解决方案2】:

因为int() 产生0,它可以与NULL 互换。 NULL 本身定义为 0,不像 C 的 NULL(void *) 0

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

int* ptr = int(5);

这仍然有效:

int* ptr = int(0);

0 是一个特殊的常量值,因此它可以被视为一个指针值。产生0 的常量表达式(例如1 - 1)也可以作为空指针常量使用。

【讨论】:

  • 另请注意,C 的 NULL 也不一定是 (void *)0。它只是一个实现定义的“值为 0 的整数常量表达式,或者这样的表达式转换为 void * 类型”。
  • @JerryCoffin 我从未使用过将NULL 定义为(void*)0 的C 编译器;它总是0(或者可能是0L)。 (但是,当 C90 使 (void*)0 在 C 中合法时,我已经在使用 C++。)
  • @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。
  • "0 是一个特殊的文字" - 只是因为它是一个常量表达式,它的特殊值是 0。(1-1) 也同样特殊,它也是一个空指针常量,所以是int()0 是文字的事实足以但不是成为常量表达式的必要条件。像strlen("") 这样的东西虽然也有特殊值0,但它不是常量表达式,因此也不是空指针常量。
  • @SteveJessop:我同意更正,这实际上是关于常量值 0,而不是 0 文字。
【解决方案3】:

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

【讨论】:

  • 这遗漏了 Jerry 的回答中的一个非常重要的细节:表达式产生值 0 是不够的,但它还必须是 constant-expression。举个反例,int f() { return 0; },表达式f() 产生值 0,但它不能用于初始化指针。
  • @DavidRodríguez-dribeas,我急于以最简单的方式给出答案,我把那部分省略了。我希望现在可以接受。
【解决方案4】:

来自n3290(C++03使用类似文字),4.10指针转换[conv.ptr]第1段(重点是我的):

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

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

【讨论】:

    【解决方案5】:

    int 不是对象。

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

    所以如果 int() 创建 0,int* 将指向内存地址 0

    【讨论】:

    • int()肯定一个对象。
    • @Tomalak:我不这么认为。这是一个临时的非类类型,就 C++ 标准而言,我认为我说这些是 not 对象是正确的。不过有点奇怪,关于“临时对象”的部分一开始只讨论了类类型的临时对象,但后来它谈到了绑定引用,当然你可以绑定对int() 的引用。定义int i;,那么毫无疑问,i是一个对象。
    • @Steve:我只希望在“对象”是 C++ 中的一个存储区域,而临时对象并没有真正的存储空间来讨论这个问题,对吧? 1.8/1 没有明确列出临时变量,但感觉好像是有意将它们包括在内。
    • @Tomalak:是的,非类类型的临时对象不需要存储,除非您参考。不过没关系,也没什么大不了的。声明“well int is not an object”是正确的,因为int 是一个类型,而不是一个对象。 int() 是产生一个对象还是仅仅产生一个右值不会影响任何人在别处所说的任何内容。
    • @Steve:这是毋庸置疑的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多