C++ temporary materialization

考虑如下代码:

struct S {
public:
    S(int i) {
        m = i;
    }
    ~S() {
        std::cout << "~S() called \n";
    }
    int m;
};

void fun(S s) {
    std::cout << "fun called \n";
}

int main()
{
    fun(S(1));
}

S(1)构造了一次,是个无名的临时对象(暂且给它取名为tmp),然后传递给fun函数,s是另一个局部对象。因此程序应打印两次~S() called。(实测vs2015打印2次,gcc和clang中只打印一次)

C++17开始,S(1)这个纯右值不一定要物化为tmp,意思是在这个程序中,根本就没有创建tmp对象。因此,在C++17支持的编译器中,只打印一次~S() called.

这绝非编译器厂家自由选择的优化技术,编译器的优化技术认为,S(1)和fun(S s)中的s是一回事,就直接在s的构造上做文章。(见《Inside C++ Model》)

C++17 强制要求纯右值prvalue只是初始化语义,意思是prvalue只能帮助其它对象初始化,自己是不能轻易物化的。这里,fun(S(1))就没有发生temporary materialization。那么,何时会发生呢?例如:

int k = fun().m;

这样子,fun()返回的纯右值不物化也不成了,因为要访问它的对象m。

其它物化条件,见 http://en.cppreference.com/w/cpp/language/implicit_conversion#Temporary_materialization

posted @ 2018-03-21 14:23  thomas76  阅读(422)  评论(0编辑  收藏  举报