编译器用来决定移动操作是否安全的标准是什么
What is the criteria that the compiler uses to decide if a move operation is safe?
给定以下代码(http://liveworkspace.org/code/5oact):
class Foo
{
public:
Foo()
{
log(__PRETTY_FUNCTION__);
}
Foo(const Foo& other)
{
log(__PRETTY_FUNCTION__);
}
Foo& operator=(const Foo& other)
{
log(__PRETTY_FUNCTION__);
return *this;
}
Foo(Foo&& other) noexcept
{
log(__PRETTY_FUNCTION__);
}
Foo& operator=(Foo&& other) noexcept
{
log(__PRETTY_FUNCTION__);
return *this;
}
~Foo(){}
};
使用这样的类:
std::vector<Foo> tt;
tt.emplace_back();
tt.emplace_back();
tt.emplace_back();
tt.emplace_back();
我得到以下输出:
Foo::Foo()
Foo::Foo()
Foo::Foo(const Foo&)
Foo::Foo()
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo()
如果我删除自定义析构函数,我会得到以下输出:
Foo::Foo()
Foo::Foo()
Foo::Foo(Foo&&)
Foo::Foo()
Foo::Foo(Foo&&)
Foo::Foo(Foo&&)
Foo::Foo()
当我声明析构函数时,为什么编译器使用复制构造函数而不是move?我知道move操作不能抛出(如果我从代码中删除noexcept
,编译器根本不会使用它),但析构函数与此有什么关系?
首先,您的编译器似乎存在使用错误noexcept规范的问题。根据标准,12.4.3:
没有异常规范的析构函数声明被隐式地认为具有与隐式声明相同的例外规范
如果所有成员和基的析构函数都是noexcept
,则析构函数的隐式声明将是noexcept
。因此,您的显式析构函数声明应该等效于:
~Foo() noexcept {} // or:
~Foo() noexcept(true) {}
但相反,您的编译器将其视为:
~Foo() noexcept(false) {}
其次,析构函数的异常规范影响是否移动的决定的原因是操作中涉及销毁。正如move构造函数上的noexcept
和move赋值操作会影响决策一样,如果在过程中可能引发异常,则不会使用move。
相关文章:
- 安全到标准:移动会员?
- 将积分类型的数组作为另一个不相关的积分类型的阵列进行访问的安全且符合标准的方法
- 标准::p set_value和线程安全
- 标准::p空气有或没有标准布局:安全reinterpret_cast?
- 标准是否保证在移动std::p ackaged_task后安全使用std::future?
- 一种安全、符合标准的方法,使类模板专用化仅在实例化时才无法使用"static_assert"进行编译
- C 标准是否保证统一初始化是例外安全
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- 标准::数组是否可安全返回
- 标准::unique_ptr和异常安全
- 将 C++ 对象强制转换为 void* 的安全/标准方法
- 根据C++标准,显式调用构造函数和析构函数是否安全
- 标准::螺纹(可拆卸)和异常安全
- Microsoft是标准::reverse_copy的安全替代品?
- C++标准容器的线程安全
- C++ - 从基类"inherit"重载赋值运算符派生类的安全/标准方法
- 是否有线程安全类变量的c++标准?
- Unicode安全查找使用boost和标准c++
- 标准库中自赋值不安全的move赋值操作符的基本原理是什么?
- 重新分配标准::地图::value_type&是否安全?