根据cppreference.com的资料, std::vector::emplace() 无条件地提供了强异常保证:
如果抛出异常(例如由构造函数引起),则容器将保持不变,就好像从未调用此函数一样(强异常保证)。
然而,在GCC 7.1.1中实际情况并非如此。以下程序:
#include <iostream>
#include <vector>
struct ugly
{
int i;
ugly(int i) : i{i} { }
ugly(const ugly& other) = default;
ugly& operator=(ugly&& other) {
if (other.i == 3) {
throw other.i;
}
i = other.i;
return *this;
}
ugly& operator=(const ugly& other) = default;
};
int main() {
std::vector<ugly> vec;
vec.reserve(6);
vec.emplace_back(0);
vec.emplace_back(1);
vec.emplace_back(2);
vec.emplace_back(4);
vec.emplace_back(5);
try {
vec.emplace(vec.begin() + 3, 3);
} catch (int i) {
}
for (const auto& u : vec) {
std::cout << u.i << "\n";
}
return 0;
}
打印
事实上,如果允许复制/移动时抛出异常,我很难看出emplace()如何可能提供强烈的保证。要在中间插入,我们必须先移动一堆元素,然后在原地构建新元素。如果其中任何一个抛出异常,我们必须将所有其他元素移回它们原来的位置,但这些移动也可能会抛出异常!那么谁错了,是cppreference还是gcc?0 1 2 4 4 5
emplace_back
的,(抱歉,更正)后面还有其他限制。 - Arne Vogel