【问题标题】:Ambiguity about the C ++ standard关于 C++ 标准的歧义
【发布时间】: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)呢?

【问题讨论】:

    标签: c++ c++11 language-lawyer


    【解决方案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 在标准中是什么意思?是调用函数的意思吗?
    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 2016-05-07
    • 2020-01-05
    • 1970-01-01
    相关资源
    最近更新 更多