【问题标题】:How to make this initialization legal in C++?如何在 C++ 中使这个初始化合法?
【发布时间】:2016-11-24 21:43:18
【问题描述】:

我在书中看过excersise,但我想不出答案:

以下代码是否合法?如果没有,你怎么能做到 合法吗?

int null = 0, *p = null;

当然,第二个是不合法的,不能把int转成int*。

主题在constexpr部分。

伙计们!这只是一个关于指针、常量和常量表达式的练习!我认为,你必须在没有 cast 和 nullptr 的情况下解决它。

【问题讨论】:

  • 这本书没有答案部分吗?它说什么?
  • 书中没有答案
  • 我仍然看不到consexpr 是如何参与其中的
  • 该部分的名称是:“Pointers and constexpr”,这就是为什么我认为您必须使用 const 和/或 constexpr 解决它
  • @AaronMcDaid 什么? pnull 在同一声明中声明。

标签: c++ c++11


【解决方案1】:

在 C++11 中,空指针常量被定义为

整数类型的整型常量表达式纯右值,计算结果为零

(C++11 [conv.ptr] 4.10/1)

这意味着在声明中添加constexpr 实际上使null 成为一个有效的空指针常量:

constexpr int null = 0, *p = null;

请注意,这被认为是一个缺陷并在 C++14 中进行了更改,因此只有整数 literal 可以是空指针常量:

一个 空指针常量 是一个值为零的整数文字 ...

(C++14 N4140 [conv.ptr] 4.10/1)

因此,有一种方法可以在 C++11 中使用 constexpr 使初始化合法,但它的存在被认为是标准缺陷并在 C++14 中被删除。因此,这本书正在教授过时的信息。

请注意,由于这是一个缺陷,编译器通常也会将此行为向后移植到其 C++11 模式(如果他们甚至首先实现了原始模式)。

【讨论】:

  • 不错!但是你很难找到一个接受这个的编译器,即使在指定 c++11 时也是如此。
  • @aaaaaaaa 原因,正如 Angew 提到的,它只对 C++11 有效,ideone 是 C++14。
  • @GillBates,指定 c++11 也无济于事 coliru.stacked-crooked.com/a/bb5c0f3603c928e0
  • @StoryTeller 在完全符合的编译器™上可以工作:)
  • @krzaq 因为它被认为是 C++11 中的一个缺陷,所以符合标准的编译器即使在 C++11 模式下也可以选择应用修复。
【解决方案2】:

另一个答案错过了使其合法的非常简单的解决方案:使null成为指针:

int *null = 0, *p = null;

但如前所述,最好的解决方案是根本不使用null 变量,而是使用标准的nullptr

【讨论】:

    【解决方案3】:

    如果你想要最小的差异,你可以选择

    int null = 0, *p = nullptr;
                           ^^^
    

    int null = 0, *p = {};
    

    int null = 0, *p = 0;
    

    最后一个示例可能会让您感到惊讶,但它的定义方式(在 C++14 中)需要使用值为 0 的整数文字。不是 int 类型的对象。


    或者,如果您不缩进对p 进行零初始化,您可以使用null 的地址对其进行初始化:

    int null = 0, *p = &null;
    

    【讨论】:

    • 第二个删掉3个字符,改一个。第一个加 3。显然第一个是最小的。
    • @Yakk 嘿,这是第一次提到的 :)
    【解决方案4】:

    您有多种选择使其合法,仅举几例:

    int null = 0, *p = 0;
    
    int null = 0, *p = nullptr;
    

    【讨论】:

      【解决方案5】:

      确实这是不合法的:

      int null = 0, *p = null;
      

      还有这个:

      int null = 0, *p = static_cast<int*>(null);
      

      这些编译,并且是等效的:

      int null = 0, *p = (int*)null;
      int null = 0, *p = reinterpret_cast<int*>(null);
      

      但应该避免,正如here 解释的那样。

      C 风格的演员(int*)null 可以被认为是 C++ 中的一种不好的做法(要清楚,这部分是见仁见智的问题),主要是因为你很难在代码中用自己的眼睛发现(那里通常没有语法高亮显示)或使用搜索/查找命令(如何将强制转换与其他类型的用法分开,例如变量声明?)。

      reinterpret_cast 更显眼,可以轻松搜索,但与 C 样式转换一样宽松,因此应避免使用它,除非您确切知道使用它的原因。

      当然,在 C++11 中一个好的初始化应该是:

      int null = 0, *p = nullptr;
      

      【讨论】:

      • 恕我直言,“好的”初始化不会使用 null 作为变量名。这不是一个真正的问题,但它看起来有点奇怪
      • 这是合法的,并且以小写命名变量使其在阅读时与NULL明显不同。我不会在我自己的代码中调用变量null,除非在一个定义明确的上下文中,比如 JSON 中的 null 值,但这也是合法的,所以使用是一个见仁见智的问题 :)跨度>
      • NULL 在 c++ 代码中总是不受欢迎,据我所知。 0 是首选项的初始值设定项。
      【解决方案6】:

      我认为您可以在 int 上使用 reinterpret_cast&lt;int*&gt; 以使其有效。

      【讨论】:

      • 我既不赞成也不反对,但据我所知,在p 的定义点,具有此转换的代码将是有效的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 2015-09-30
      • 2013-01-23
      相关资源
      最近更新 更多