关于 C++ 标准的歧义
Posted
技术标签:
【中文标题】关于 C++ 标准的歧义【英文标题】:Ambiguity about the C ++ standard 【发布时间】:2020-11-26 08:19:56 【问题描述】:根据这段代码:
#include <iostream>
using namespace std;
struct T
T() cout << "default"<<endl;
T(string s) cout << "ctor "<< endl;
T(const T& t) cout << "copy ctor"<< endl;
;
int main()
T x = T(T(T()));
return 0;
输出:
default
并根据standard:
(17) 初始化器的语义如下。目的地 type 是正在初始化的对象或引用的类型,并且 source type 是初始化表达式的类型。如果 初始值设定项不是单个(可能是带括号的)表达式, 源类型未定义。
.....
(17.6.1) 如果初始化表达式是纯右值并且 源类型的 cv 非限定版本与 目标的类,初始化表达式用于 初始化目标对象。 [例子:T x = T(T(T()));来电 T 默认构造函数来初始化 x。 —结束示例]
它在 c ++ 11 (GNU GCC v7.1.1) 中给出相同的结果
第一个问题: 此语句中是否定义了源类型?
T x = T(T(T()));
现在如果我们将这个函数添加到这段代码中:
string f(T t) return "str";
并将T x = T(T(f(T())));
替换为T x = T(T(T()));
输出:
default
ctor
现在是否定义了源类型?
T()
不是初始化表达式吗?
如果是按照标准应该调用默认构造函数,但是为什么要为x调用T(string s)
呢?
【问题讨论】:
【参考方案1】:此语句中是否定义了源类型?
T x = T(T(T()));
是的,因为T(T(T()))
是单个表达式;在这种情况下,它可以被paranthesized。
同样的道理也适用于
T(T(f(T())))
因为这也是一个表达式。
不是 T() 初始化表达式吗?
一般情况下是可以的,但在上述情况下则不然。 =
和 ;
之间的整个表达式是初始化表达式。
但为什么要为 x 调用 T(string s)?
因为对f
的显式调用会返回string
,并且该参数用于构造T
,而T
会调用string
构造函数。
T x = T( T(f( T() )) );
// ^^^ calls the default constructor
// ^^^^^^^^^^^^^ calls the string constructor
【讨论】:
我有点困惑 标准中初始化表达式的确切含义是什么?这个词的标准含义是什么?最外部的T()?最内部的T()?(关于我们什么时候有一个函数) 如答案中所述,initializer-expression 是=
和;
之间的表达式,即声明中的...
喜欢T t = ... ;
好的,但根据标准,初始化表达式用于初始化目标对象。根据你的说法,初始化表达式是表达式在=
和;
之间也就是最外部的T(),那么为什么不调用copy-ctor(当是这样的时候:T t = T(T(T()))
)?
语法是copy-initialization。尽管有名字,但没有调用复制构造函数,复制省略将处理“临时”T
s。
可以解释更多关于is used
的信息。这个is used
在标准中是什么意思?是调用函数的意思吗?以上是关于关于 C++ 标准的歧义的主要内容,如果未能解决你的问题,请参考以下文章