bad_alloc通过右值和对象有效性插入对象时
bad_alloc upon inserting object by rvalue and object validity
考虑以下代码(假设 SomeClass 具有移动构造函数和指针等字段,这些字段在对象与另一个对象交换其内容后将失效(:
SomeClass data;
std::list queue;
try { queue.push_back(std::move(data)); }
catch(std::bad_alloc)
{
data.doThingsUsingObjectData(); //Can I do this here?
return;
}
data.doThingsUsingObjectData(); //Definitelly can't do this here - object was invalidated
关键是 - 如果在使用 std::move(( 将对象添加到 STL 时抛出bad_alloc,这是否意味着我试图通过右值添加到 STL 的对象实际上仍然有效,我可以访问它而不必担心未定义的行为?
std::list
将其元素存储在节点中。当您添加一个元素时,将分配一个新节点,然后将该元素存储在节点中(通过调用 std::allocator_traits<A>::construct
,这通常会执行放置 new,以在节点内就地构造对象(,最后通过更新新节点和相邻节点的指针将其链接到列表中,将节点添加到列表中。
如果抛出bad_alloc
异常,则只能来自分配新节点,或来自在节点内构造元素(因为更新指针不会抛出任何内容(。
如果在分配节点对象时发生异常,那么很可能该对象尚未被移动,因为没有尝试移动构造新元素(在有节点构造它之前,您无法这样做!不能保证容器在节点内构造最终元素之前不会创建中间变量,但这将是一个质量很差的实现,因为没有理由这样做。
如果类具有非抛出移动构造函数,那么您就知道异常一定来自节点分配。否则,如果异常来自构造元素,则 rvalue 参数的状态将由相关类的异常安全保证决定。
简而言之,如果std::list
实现不好,或者插入的对象在移动构造期间可能会抛出并且没有强大的异常安全保证,那么右值参数可能会处于移自状态。但除此之外,您应该能够依赖它未修改。
这取决于为什么抛出异常,但一般来说,否。移动操作后,对象处于未指定状态。请参考这个问题。
容器可能会也可能不会使用 SomeClass
的 move 构造函数,但是当您使用 std::move 时,您将对象标记为右值引用,您不应该在使用对象(或传递它(作为右值引用后使用它。
作为一种好的做法,如果您考虑重用对象,则永远不要使用 std::move。
IIRC标准规定,从中移出的对象保持未指定的状态。这意味着您可以调用成员方法,只要它们不依赖于对象的特定状态,它们就应该正常工作。需要参考
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 智能指针列表-管理对象生存期和指针有效性
- bad_alloc通过右值和对象有效性插入对象时
- 测试C++对象的有效性,就好像它是一个指针一样
- std::d eque 会保留其包含对象的指针有效性吗?
- 对 boost::smart_ptr 的引用指向对象并检查其有效性