我正在使用emplace_back
向std::deque
添加项目。在构造过程中,新项目可能会将其他项目添加到正在构建的std::deque
中。这导致非常有趣的行为。请考虑以下代码段:
#include <iostream>
#include <deque>
#include <string>
struct foo
{
std::string m_marker;
foo(std::deque<foo>& into, const std::string& marker, bool createInner = true)
: m_marker(marker)
{
if (createInner)
{
std::cout << "Marker is " << m_marker << std::endl;
into.emplace_back(into, "my other marker", false);
std::cout << "Marker is now " << m_marker << std::endl;
}
}
};
int main()
{
std::deque<foo> foos;
foos.emplace_back(foos, "my initial marker");
std::cout << "There are " << foos.size() << " items in the deque:" << std::endl;
for (foo& f : foos)
{
std::cout << f.m_marker << std::endl;
}
}
它会创建deque
个foo
个对象。第一个对象的标记为"my initial marker"
,由于createInner
为true
,因此它将创建第二个对象。我希望得到以下结果:
Marker is my initial marker
Marker is now my initial marker
There are 2 items in the deque:
my initial marker
my other marker
然而,对于clang ++(tags / Apple / clang-421.11.66)和libc ++(不确定它是什么版本),这就是我得到的:
Marker is my initial marker
Marker is now my other marker
There are 2 items in the deque:
my other marker
如您所见,第一个对象的m_marker
字段被第二个对象覆盖,而在双端队列中显示的第二个字段现在为空。显然,某处存在一个错误,它必须是在调用deque
期间修改emplace_back
或者libc ++没有完成其工作时未定义的行为。它是哪一个?
答案 0 :(得分:2)
正如Howard Hinnant回答on the bug report,标准没有说明这个案例,但需要说它会导致未定义的行为:
在每种情况下,由于例外安全考虑, 容器在构造foo之前不会被“改变” 完成。这样,如果foo构造函数抛出容器 国家没有变化。例如,vector.size()直到被改变 foo构造函数完成了。所以当第二个 施工在第一个完工之前开始,它仍然是 附加到零长度向量。
这不是可以在实施中解决的问题 容器。标准需要说“不要那样做”。
所以不要指望它适用于任何实现。