正如我们所知,当新元素添加到std :: vector(通过push_back)时,它可能缺少空间,对于这些情况,vector会分配更大的内存块来保存其所有元素,然后从现有块转移到在C ++ 98中,这是通过从旧位置复制元素然后销毁这些对象来完成的,因此它可以提供强大的异常保证,在c ++ 11中,它可以使用移动构造函数进行优化,前提是它不是新的但是如果我的析构函数是noexcept(false),那么为什么不进行优化会发生什么呢?
#include <iostream>
#include <vector>
class X
{
public:
X()
{
}
X(const X& ob) noexcept
{
std::cout<<"Copy Constructor...."<<std::endl;
}
X(X&& ob) noexcept
{
std::cout<<"Move Constructor...."<<std::endl;
}
~X() noexcept(false)
{
}
};
int main()
{
std::vector<X> myobs;
for(int i=0;i<1000;i++)
{
myobs.push_back(X());
}
return 0;
}
为什么在上面的场景中调用了复制构造函数,并且还注意到如果我将析构函数设置为noexcept(默认行为),那么只会调用移动构造函数。
为了增加我对强异常保证的理解(在vector :: push_back中),旧内存中的所有元素都不会被销毁,直到所有元素都被成功复制,这意味着在最后调用析构函数,所以它们是否无关紧要是noexcept或不是
答案 0 :(得分:4)
问题在于is_nothrow_move_constructible<T>
的规范,当前指定用于检查表达式
T(declval<T&&>())
是noexcept,但它涉及析构函数(临时的)以及移动构造函数。这可以说是一个图书馆缺陷,是正在进行的LWG 2116的主题。 GCC遵循规范是正确的;规范本身就很糟糕。