c++ - 复制省略和异常(exception)

标签 c++ exception copy-constructor

在阅读了 cppreference 的复制省略之后我想玩异常(exception)和复制省略。 所以我在 coliru 上用 gcc 7.2 写了下面的代码

#include <iostream>

class Exception
{
public:
    Exception() { std::cout << "constructed\n"; }
    Exception(Exception& other) {std::cout << "copy constructed\n";}
    Exception(const Exception& other) {std::cout << "copy constructed\n";}
    Exception(Exception&& other) {std::cout << "move constructed\n";}
};

void foo()
{
    throw Exception();
}

int main()
{
    try
    {
        foo();
    }
    catch(Exception e )
    {

    }
}

输出

constructed
copy constructed

我们可以看到调用了复制构造函数,即使在使用 -O2 调用 gcc 时也会发生这种情况。 在我看来,根据以下条款,这段代码应该有资格复制省略:

When handling an exception, if the argument of the catch clause is of the same type (ignoring top-level cv-qualification) as the exception object thrown, the copy is omitted and the body of the catch clause accesses the exception object directly, as if caught by reference.

那么为什么要调用拷贝构造函数呢?为什么复制省略在这种情况下不起作用?

最佳答案

cppreference 对此不准确。事实上,除了在常量表达式 (constexpr) 或常量初始化(静态或线程-本地的)。在您的示例中情况并非如此。

参见 [class.copy.elision]/1在当前的 C++17 草案中(强调我的):

When certain criteria are met, ... elision of copy/move operations, called copy elision, is permitted in the following circumstances:

— 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 can be omitted by constructing the automatic object directly into the exception object

Copy elision is required where an expression is evaluated in a context requiring a constant expression and in constant initialization.

这意味着有一天它可能会作为编译器优化来实现,但目前并非如此。

因此,暂时用 const&catch 是明智的(也可以避免意外切片)。

关于c++ - 复制省略和异常(exception),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48259160/

相关文章:

java - 如何为 Crawler4J 编写自己的异常处理?

zend-framework - 我无法使用 try....catch 捕获 php 异常

C++ - 为什么可以在复制构造函数中直接访问传递的对象的私有(private)变量?

c++ - 哎呀概念-得到意想不到的结果

c++ - 在 C++ Win32 中哪个 Windows SDK 最适合我?

c++ - Qt 应用程序图标不起作用

c++ - 如果不是直接从代码中使用,为什么要包含 <string>?

java - 我们可以在 Java 中捕获错误吗?

c++ - 为什么 move ctor 比 copy ctor 慢?

c++ - 如何让最小化和最大化按钮出现在 wxDialog 对象上