【问题标题】:Are these vector definitions "constant initialization"?这些向量定义是“不断初始化”吗?
【发布时间】:2015-12-07 10:26:45
【问题描述】:

这个问题是关于代码(在命名空间范围内):

std::vector<int> v1;
std::vector<int> v2(4);

在 C++14 (N4140) 的第 3.6.2 节中定义了一个术语常量初始化

不断初始化:

  • [省略 - 关于引用初始化]
  • 如果具有静态或线程存储持续时间的对象由构造函数调用初始化,并且初始化完整表达式是该对象的常量初始化器;
  • 如果具有静态或线程存储持续时间的对象未通过构造函数调用进行初始化,并且该对象是值初始化的,或者出现在其初始化程序中的每个完整表达式都是常量表达式。

此外,术语常量初始化器在前面定义过:

对象o常量初始化器是一个表达式,它是 常量表达式,除了它还可以为 o 及其子对象调用 constexpr 构造函数,即使这些对象是非文字类类型。

所以,看看std::vector&lt;int&gt; v2(4)

此对象由构造函数调用初始化,因此它被第二个要点覆盖。初始化完整表达式为44 是一个常量表达式,因此它是一个常量初始化器。所以满足了第二个要点,这应该是常量初始化的情况。

但是,我用一些编译器进行了测试,它们似乎都将v2 视为动态初始化

对于v1 的情况,不清楚这是否算作“由构造函数调用初始化”;如果是这样,初始化完整表达式会是什么。

我的问题是:v1v2常量初始化,还是动态初始化;如果是后者,能否解释一下标准中的这些引用是如何解释的?

【问题讨论】:

  • @KerrekSB 我上面引用的文字来自 [basic.start.init]/2。也许它被认为是有缺陷的并在以后的草稿中被替换? N4296 仍然有相同的文本,这是我的最新草稿。
  • 好吧,没关系。我认为措辞涵盖了构造函数必须是 constexpr 的事实,但在以前的修订版中可能不清楚。见CWG 2026 可能吗? (编辑:)实际上,不,我认为更改不会影响您的观点。关于constexpr 的措辞似乎没有改变。

标签: c++ initialization language-lawyer c++14


【解决方案1】:

根据 1.9/10,初始化的完整表达式包括对构造函数的调用:

full-expression 是不是另一个表达式的子表达式的表达式。 ...如果定义语言构造以产生函数的隐式调用,则使用该语言 就本定义而言,construct 被认为是一个表达式。 ... 应用于表达式结果的转换以满足语言的要求 出现表达式的结构也被认为是完整表达式的一部分。
[ 例子:
...

S s1(1); // full-expression is call of S::S(int)

然后,根据 8.5/17,直接初始化(v1v2 都使用)涉及构造函数调用。

因此,根据您引用的第二个要点,构造函数调用是“初始化完整表达式”的一部分。所以构造函数调用,而不仅仅是4,是完整的表达式。这反过来意味着这样的构造函数必须是 constexpr 才能成为 constant initializer (根据它的定义,正如你所引用的那样)。而且由于std::vector的默认构造函数和size_t构造函数都不是constexpr,所以初始化不是常量。

【讨论】:

  • 我明白了。所以S s1(1); 是一个完整的表达式,即使它不是一个表达式
  • @M.M 差不多。虽然从技术上讲,只有对 S::S(int) 的调用是完整的表达式,而不是声明本身。
猜你喜欢
  • 2013-12-31
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 2021-09-23
  • 2020-08-10
  • 1970-01-01
相关资源
最近更新 更多