为什么在向量重新分配期间没有调用 noexcept 移动构造函数?
Why noexcept move constructor is not getting called during vector reallocation?
正如我们所知,当新元素添加到 std::vector(通过 push_back)时,它可能缺少 space,对于这些情况,vector 会分配更大的内存块保留它的所有元素,然后从现有块转移到新的 one.In C++98,这是通过从旧位置复制元素然后销毁这些对象来完成的,因此它可以提供强大的异常保证,在 C++ 中11 它可以使用移动构造函数进行优化,前提是它是 noexcept 但是如果我的析构函数是 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 中)的理解是 none 旧内存中的元素被销毁,直到所有元素都被成功复制,这意味着最后调用析构函数所以不管他们是不是 noexcept 与否
问题出在 is_nothrow_move_constructible<T>
的规范上,目前指定的规范是检查表达式
T(declval<T&&>())
是 noexcept,但这涉及(临时的)析构函数以及移动构造函数。这可以说是库缺陷,是正在进行的 LWG 2116 的主题。 GCC遵循规范是正确的;是规范本身不好。
正如我们所知,当新元素添加到 std::vector(通过 push_back)时,它可能缺少 space,对于这些情况,vector 会分配更大的内存块保留它的所有元素,然后从现有块转移到新的 one.In C++98,这是通过从旧位置复制元素然后销毁这些对象来完成的,因此它可以提供强大的异常保证,在 C++ 中11 它可以使用移动构造函数进行优化,前提是它是 noexcept 但是如果我的析构函数是 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 中)的理解是 none 旧内存中的元素被销毁,直到所有元素都被成功复制,这意味着最后调用析构函数所以不管他们是不是 noexcept 与否
问题出在 is_nothrow_move_constructible<T>
的规范上,目前指定的规范是检查表达式
T(declval<T&&>())
是 noexcept,但这涉及(临时的)析构函数以及移动构造函数。这可以说是库缺陷,是正在进行的 LWG 2116 的主题。 GCC遵循规范是正确的;是规范本身不好。