下面显示的代码段中没有省略移动构造函数是否有任何特殊原因?
Is there any special reason why the move constructor is not elided in the snippet shown below?
gcc,clang 和 VS2015 在抛出对象 a
后,不会省略下面代码中对移动构造函数的调用。在我看来,§8.12[class.copy]/31 (N4140) 的要点 (31.2) 中确立的条件已得到满足。
#include <iostream>
struct A
{
A() { std::cout << "Default ctor " << '\n'; }
A(const A& a) { std::cout << "Copy ctor" << '\n'; }
A(A&& a) { std::cout << "Move ctor" << '\n'; }
~A() { std::cout << "Destructor " << '\n'; }
};
int main()
{
try
{
A a;
throw a;
}
catch(A& a) { std::cout << "Caught" << '\n'; }
}
注意a
是一个左值,但是根据§12.8/32,重载决议
到 select 副本的构造函数首先执行,就好像对象是由右值指定的一样。也就是说,调用移动构造函数是可以的。如果您删除上面移动构造函数的定义,将调用复制构造函数,但同样,它不会被删除!
我知道复制省略不是标准强制要求的,但我很想知道是否有任何特殊条件可以证明上述三个编译器避免这种优化,特别是在这个特殊情况下例如。
gcc 的示例输出,来自上面的 link:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Default ctor
Move ctor
Destructor
Caught
Destructor
根据 12.8 [class.copy] 第 31 段,第二个项目符号可以省略被抛出的局部变量的副本:
in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost
enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object
似乎 none 的编译器利用了这种优化。一个原因可能是,就将精力花在其他优化上而言,这样做根本不值得。我认为标准中没有任何内容禁止这种优化。
gcc,clang 和 VS2015 在抛出对象 a
后,不会省略下面代码中对移动构造函数的调用。在我看来,§8.12[class.copy]/31 (N4140) 的要点 (31.2) 中确立的条件已得到满足。
#include <iostream>
struct A
{
A() { std::cout << "Default ctor " << '\n'; }
A(const A& a) { std::cout << "Copy ctor" << '\n'; }
A(A&& a) { std::cout << "Move ctor" << '\n'; }
~A() { std::cout << "Destructor " << '\n'; }
};
int main()
{
try
{
A a;
throw a;
}
catch(A& a) { std::cout << "Caught" << '\n'; }
}
注意a
是一个左值,但是根据§12.8/32,重载决议
到 select 副本的构造函数首先执行,就好像对象是由右值指定的一样。也就是说,调用移动构造函数是可以的。如果您删除上面移动构造函数的定义,将调用复制构造函数,但同样,它不会被删除!
我知道复制省略不是标准强制要求的,但我很想知道是否有任何特殊条件可以证明上述三个编译器避免这种优化,特别是在这个特殊情况下例如。
gcc 的示例输出,来自上面的 link:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Default ctor
Move ctor
Destructor
Caught
Destructor
根据 12.8 [class.copy] 第 31 段,第二个项目符号可以省略被抛出的局部变量的副本:
in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object
似乎 none 的编译器利用了这种优化。一个原因可能是,就将精力花在其他优化上而言,这样做根本不值得。我认为标准中没有任何内容禁止这种优化。