C++ Visual Studio 2015附带的std::vector实现的异常安全性
考虑以下计划:C++ Visual Studio 2015附带的std::vector实现的异常安全性,c++,vector,visual-studio-2015,stl,c++14,C++,Vector,Visual Studio 2015,Stl,C++14,考虑以下计划: #include <iostream> #include <vector> #include <type_traits> struct X { int state; X() : state(0) {}; X(int x) : state(x) {}; X(X const& y) noexcept : state(1) {} X(X&& y) noexcept(false) : st
#include <iostream>
#include <vector>
#include <type_traits>
struct X
{
int state;
X() : state(0) {};
X(int x) : state(x) {};
X(X const& y) noexcept : state(1) {}
X(X&& y) noexcept(false) : state(y.state != 8 ? 2 : throw 1)
{ y.state = 0; }
X& operator =(X const&) = default;
X& operator =(X&&) = default;
};
int main() {
std::vector<X> a;
a.reserve(2u);
a.emplace_back(6);
a.emplace_back(8);
try {
// ####
std::cout << 'A' << a.front().state << a.back().state;
}
catch (...)
{
std::cout << 'B' << a.front().state << a.back().state;
}
return 0;
}
那么,为什么我希望在所有情况下都是A11
1:a.resize(10u,X{})代码>
[vector.capacity],n4140和n4606的16/17表示关于空隙大小调整(尺寸类型sz,常数T&c)代码>
要求:T
应可插入*此中
备注:如果引发异常,则不会产生任何影响
因此,如果编译器必须保证在异常情况下可以完全回滚(“无效果”),那么它必须复制元素,或者只能在移动不异常的情况下移动,因为移动会立即影响无法回滚的元素(这只有在moving将抛出时才有必要,而noexcept move构造函数则不是这样)
因此,我希望A11
作为输出(或者B68
,如果复制构造函数抛出)
2:xb;a.向后推(b);
3:a.emplace_back(1);
n4140和n4606中的[vector.modifiers]一个表示:
如果在末尾插入单个元素时引发异常,并且T
是CopyInsertable
或是\u nothrow\u move\u constructible::value
是true
,则不会产生任何影响
同样,当类型为“CopyInsertable”(X为CopyInsertable)时,如果出现异常,标准要求“无效”。->如果没有异常,则移动
我对这些指令的解释是,A11
是预期的输出(或者换句话说,一致的std::vector不应该移动它的元素,除非移动不是例外或者复制是不可能的)
我试图查找有关VS SL的一些信息,但在VS博客上只找到一篇博客文章“”,表明VS标准库实现是“功能完整的”,我不知道这是否应该声称符合标准
注意:我怀疑我是第一个发现VS在实际复制元素时错误地移动了元素的人——如果有人有连接问题,不要避免指向它
因此,问题是:MSVC中的行为是否有特定的原因(即复制与移动或其他任何操作以外的性能影响),或者这是否是一个bug?是否是:state(state!=8?2:throw 1)
在初始化之前访问state
时导致UB?您是否打算编写X(X&&X)noexcept(false):state(x.state!=8?2:throw 1){}
@SimonKraemer:的确:)看起来像个bug。你可以检查向量实现,看看它是如何完成的。在libstd++中,它们有一个\u move\u if\u noexcept
(或类似的东西)复制而不是移动移动将抛出的位置。@Arunmu:据我所知,MSVC使用std::memmove
来处理普通类型或\u Al.construct(\u undance(\u Dest),\u std move(*\u First))
在一般情况下,如果没有异常,它应该是移动的。嗯,不确定这是否是一个错误。根据与std:vector一起使用的类型,它必须是可移动的,这似乎定义为tu=rv;u等于构建之前的rv值
(有关更多示例,请参阅链接文档)您的状态
未实现。此外,在末尾插入单个元素时不会引发异常。
statement g++ msvc expected
1 a.resize(10u, X{}); A11 B08 A11
2 X b; a.push_back(b); A11 B08 A11
3 a.emplace_back(1); A11 B08 A11