Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过右值和对象有效性插入对象时的错误分配_C++_Stl_Move_Rvalue_Bad Alloc - Fatal编程技术网

C++ 通过右值和对象有效性插入对象时的错误分配

C++ 通过右值和对象有效性插入对象时的错误分配,c++,stl,move,rvalue,bad-alloc,C++,Stl,Move,Rvalue,Bad Alloc,考虑以下代码(假设SomeClass具有移动构造函数和指针之类的字段,这些字段在对象与另一个对象交换内容后将失效): 问题是-如果在使用std::move()将对象添加到STL时抛出bad_alloc,这是否意味着我试图通过右值添加到STL的对象实际上仍然有效,并且我可以访问它而不必担心未定义的行为?这取决于引发异常的原因,但一般来说,否。移动操作后,对象处于未指定状态。请参阅 容器可以也可以不使用SomeClass的move构造函数,但是当您使用std::move时,您将对象标记为右值引用,在

考虑以下代码(假设SomeClass具有移动构造函数和指针之类的字段,这些字段在对象与另一个对象交换内容后将失效):


问题是-如果在使用std::move()将对象添加到STL时抛出bad_alloc,这是否意味着我试图通过右值添加到STL的对象实际上仍然有效,并且我可以访问它而不必担心未定义的行为?

这取决于引发异常的原因,但一般来说,否。移动操作后,对象处于未指定状态。请参阅

容器可以也可以不使用
SomeClass
的move构造函数,但是当您使用std::move时,您将对象标记为右值引用,在使用(或传递)对象作为右值引用后不应使用该对象

作为一个好的实践,如果您考虑重用对象,就不应该使用std::move


IIRC是一种标准状态,表示从中移动的对象仍处于未指定状态。这意味着您可以调用成员方法,只要它们不依赖于对象的特定状态,它们就应该正常工作需要引用

A
std::list
将其元素存储在节点中。添加元素时,会分配一个新节点,然后将元素存储在该节点中(通过调用
std::allocator\u traits::construct
,该调用通常会进行新的放置以在节点内构建对象),最后通过更新新节点和相邻节点的指针将节点添加到列表中(s) 将其链接到列表中

如果抛出
bad_alloc
异常,则只能从分配新节点或在节点内部构造元素(因为更新指针不会抛出任何东西)中抛出异常

如果在分配节点对象时发生异常,则很可能该对象尚未从中移动,因为未尝试移动构造新元素(在有节点将其构造到其中之前,无法执行此操作!)。无法保证容器在构造节点内的最终元素之前不会创建中间变量,但这将是一个低质量的实现,因为没有理由这样做

如果类具有非抛出移动构造函数,则您知道异常必须来自节点分配。否则,如果异常来自构造元素,则右值参数的状态将由相关类的异常安全保证决定


因此,简而言之,如果
std::list
实现不好,或者插入的对象在move构造期间可能抛出,并且没有强大的异常安全保证,那么rvalue参数可能处于moved from状态。但是,否则,您应该能够依赖于它未被修改。

我不认为move makes对象无效。好吧,我没有精确-假设某个类的字段在对其对象调用std::move()后将保持无效(即指针)。我不确定指针“无效”是什么意思。我认为它们将处于可预测状态(当然,我指的是智能指针),因此,如果您在取消引用之前检查它们,您应该会没事。@PookyFan,if
queue.push\u back
在抛出
bad\u alloc
数据之前将
data
分配给一个临时变量(根据您的设计).所以,我认为这是不可能的guarantee@PookyFan,我在标准中没有发现这方面的任何内容,所以是的,这将是实施dependent@PookyFan,我不会把我的答案标记为正确的,最好等另一个答案好吧,随你的便。@user1708860,只需执行
std::move(x)
不会以任何方式改变
x
。该对象只会被修改,如果其他函数对其执行操作,则可能会进入未指定的状态。@JonathanWakely我从来没有说过它会这样做。“当您使用std::move时,您将对象标记为代码中该点的右值引用,因此对象的状态未指定”当然可以这样理解。
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