gpt4 book ai didi

c++ - 面对抛出移动构造函数/赋值运算符,std::vector::emplace() 是否真的提供了强大的异常保证?

转载 作者:可可西里 更新时间:2023-11-01 17:39:59 35 4
gpt4 key购买 nike

According to cppreference.com , std::vector::emplace() 无条件提供强异常保证:

If an exception is thrown (e.g. by the constructor), the container is left unmodified, as if this function was never called (strong exception guarantee).

但是,在 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;
}

打印

0
1
2
4
4
5

事实上,如果允许复制/移动抛出异常,我很难看出 emplace() 如何提供强有力的保证。要放置在中间,我们必须先将一堆元素移开,然后在其位置构建新元素。如果其中任何一个抛出,我们必须将所有其他元素移回它们原来的位置,但这些移动也可以抛出!

那么谁错了,是 cppreference 还是 gcc?

最佳答案

根据 C++14 标准,强异常保证仅在您插入的类型本身具有强异常保证时才有效。

这里:

23.3.6.5 vector modifiers [ vector.modifiers ]

iterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
iterator insert(const_iterator position, size_type n, const T& x);
template <class InputIterator>
iterator insert(const_iterator position, InputIterator first, InputIterator last);
iterator insert(const_iterator position, initializer_list<T>);
template <class... Args> void emplace_back(Args&&... args);
template <class... Args> iterator emplace(const_iterator position, Args&&... args);
void push_back(const T& x);
void push_back(T&& x);

1 Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid. If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation there are no effects. If an exception is thrown while inserting a single element at the end and T is CopyInsertable or is_nothrow_move_constructible::value is true, there are no effects. Otherwise, if an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.

所以它看起来像cppreference.com是错误的。

关于c++ - 面对抛出移动构造函数/赋值运算符,std::vector::emplace() 是否真的提供了强大的异常保证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45125134/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com