参考http://en.wikipedia.org/wiki/Copy_elision
我在代码下面运行:
#include <iostream>
struct C {
C() {}
C(const C&) { std::cout << "Hello World!\n"; }
};
void f() {
C c;
throw c; // copying the named object c into the exception object.
} // It is unclear whether this copy may be elided.
int main() {
try {
f();
}
catch(C c) { // copying the exception object into the temporary in the exception declaration.
} // It is also unclear whether this copy may be elided.
}
我得到的输出:
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ make clean
rm -f Trial.exe Trial.o
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ make
g++ -Wall Trial.cpp -o Trial
Gaurav@Gaurav-PC /cygdrive/d/Trial
$ ./Trial
Hello World!
Hello World!
据我所知,编译器可能已经使用不必要的复制优化了代码,但这并没有在这里进行。
但我想问的是,two calls to the copy constructor
是如何制作的?
catch(C c)
- 因为我们正在传递值,所以这里调用了复制构造函数。
但是在throw c
如何调用复制构造函数?有人可以解释一下吗?
答案 0 :(得分:12)
throw c;
创建一个临时对象,抛出此临时对象。临时的创建可能是通过复制/移动构造函数。是的,这个复制/移动可以省略。
<强>参考文献:强>
C ++ 11 15.1抛出异常
§3:
throw-expression初始化一个临时对象,称为异常对象,其类型是通过从throw和adjust的操作数的静态类型中删除任何顶级cv限定符来确定的。类型.........
§5:
当抛出的对象是类对象时,即使复制/移动操作被省略,也应该可以访问复制/移动构造函数和析构函数(12.8)。
答案 1 :(得分:0)
在复制并移动构造函数时抛出用户定义的类型对象
struct demo
{
demo() = default;
demo(demo &&) = delete;
demo(const demo &) = delete;
};
int main()
{
throw demo{};
return 0;
}
error: call to deleted constructor of 'demo'
throw demo{};
^~~~~~
note: 'demo' has been explicitly marked deleted here
demo(demo &&) = delete;
^
1 error generated.
compiler exit status 1