C++ noexcept与move_if_noexcept详解 | 异常安全保证

C++ noexcept与移动语义:保证异常安全 #

引言 #

在C++中,noexcept修饰符不仅是一个简单的声明,它还与移动语义和容器的异常安全性密切相关。

之前在训练营和大家一起讨论过vector等动态扩容容器的扩容机制,结论是可以move的话,会优先move,其次才是copy。

为什么可以move,需要定义类的移动构造函数,看这段代码:

struct Foo {
    Foo() {}
    ~Foo() noexcept {}
    Foo(const Foo&) { 
        std::cout << "copy \n"; 
    }
    Foo(Foo&&) { 
        std::cout << "move \n"; 
    }
};

int main() {
    std::vector<Foo> v;
    for (int i = 0; i < 3; ++i) {
        v.emplace_back();
    }
}

然而这里输出的都是copy,和上述的结论貌似不符。

我们再稍微改动一下代码:

struct Foo {
    Foo() {}
    ~Foo() noexcept {}
    Foo(const Foo&) { 
        std::cout << "copy \n"; 
    }
    Foo(Foo&&) noexcept { 
        std::cout << "move \n"; 
    }
};

这时输出的都是move。

这里唯一的改动就是为移动构造函数添加了 noexcept 修饰。只有它使用noexcept修饰,只有在保证不抛出异常的情况下( 强异常安全保证),自动扩容时才会选择move语义,这就叫move_if_noexcept。

那为什么要有move_if_noexcept?

具体可以看看这两个文档:

参考资料 #