C++ 异常和复制构造函数:C++;

C++ 异常和复制构造函数:C++;,c++,C++,指 我运行以下代码: #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 co

我运行以下代码:

#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.
}
我知道编译器可能已经用不必要的复制对代码进行了优化,但这里没有这样做

但是我想问的是,
如何对复制构造函数进行两次调用

catch(cc)
-因为我们是按值传递的,所以在这里调用复制构造函数

但是在抛出c时,如何调用复制构造函数?有人能解释一下吗

throw c;     
创建一个临时对象,并抛出该临时对象。可以通过复制/移动构造函数创建临时文件。是的,这种复制/移动可以省略


参考文献:
C++11 15.1引发异常

§3:

抛出表达式初始化一个临时对象,称为异常对象,其类型是通过从抛出操作数的静态类型中删除任何顶级cv限定符并调整类型来确定的

§5:

当抛出的对象是类对象时,即使省略了复制/移动操作,复制/移动构造函数和析构函数也应可访问(12.8)


在抛出用户定义的类型对象时复制并移动构造函数

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
  • 如果我们通过值捕获异常,我们也可能期望复制省略(允许编译器这样做,但这不是强制性的)。初始化catch子句参数时,exception对象是一个左值参数

From:

Alok-你能给我举个移动构造函数的例子吗?它与移动赋值运算符相同吗?请你回复
EDIT
部分是@BenVoigt的问题,这些评论似乎比问题更自信,这可能是因为它们直接来自维基百科。在这里,“初始化一个临时对象”是缺少的。@GauravK:C++11除了C++03中已经存在的复制语义外,还引入了移动语义。这个问题可能是一个很好的开始。@GauravK:是的,在C++11中介绍过。通常情况下,您不应该也不能依赖计算复制/移动构造函数调用。一个好的编译器将尽可能通过RVO或NRVo应用复制省略。
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