为什么为这个未命名的临时构造函数省略,在正常初始化时有副作用,但在大括号列表初始化时没有



我想测试一个临时对象是否至少与持有常量引用的临时对象一样长,所以我想出了这个例子。

#include <iostream>
struct Test {
    Test() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    ~Test() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};
struct Holder {
    Holder(const Test& t):m_t(t) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    ~Holder() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    const Test& m_t;
};
int main() {
    Holder(Test());
    return 0;
}

但是,我很惊讶地看到编译器实际上已经优化了整个事情,正如在codebolt上看到的那样。

但是,如果我真的给临时起了一个名字,通过改变行

Holder(Test());

Holder h((Test()));

然后它"神奇地"起作用:代码螺栓。

情节扭曲:如果我切换到 c++11 并对 Holder 类使用支撑列表初始化,那么无论我是否为临时命名,都不会省略构造函数。再次查看代码螺栓。

那么这是怎么回事呢?我的印象是,具有副作用的构造函数永远不会被省略,但我显然错过了在版本之间更改的标准中的一个重要部分。

谁能给我一个提示?

这是

最令人烦恼的解析问题:Holder(Test());声明一个名为 Test 的函数,该函数返回 Holder 并接受 0 个参数。

使用 g++ 使用以下代码:

#include <iostream>
#include <type_traits>
struct Test {};
struct Holder { Holder(Test); };
template<class T>
char const* f() { return __PRETTY_FUNCTION__; }
int main() {
    Holder(Test());
    std::cout << f<decltype(&Test)>() << 'n';
}

输出:

const char* f() [with T = Holder (*)()]

一个简单的解决方法是使用 C++11 大括号进行初始化:Holder(Test{});Holder{Test{}};

最新更新