关于 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。尽管有名字,但没有调用复制构造函数,复制省略将处理“临时”Ts。 可以解释更多关于is used的信息。这个is used 在标准中是什么意思?是调用函数的意思吗?

以上是关于关于 C++ 标准的歧义的主要内容,如果未能解决你的问题,请参考以下文章

关于标准 C++ 多线程的简单问题 [重复]

关于引用的一点理解歧义

一些关于广泛使用的C++标准库STL的思考

一些关于广泛使用的C++标准库STL的思考

关于C++标准库string和vector???

c++标准库中没有关于正则匹配字符串的函数么