c++ - 在调用 emplace_back 期间修改 std::deque 是否合法?

标签 c++ c++11 language-lawyer deque libc++

我正在使用 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;
    }
}

它创建一个 dequefoo 对象。第一个对象的标记是 "my initial marker",由于 createInnertrue,它将创建第二个对象。我希望得到以下结果:

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 字段被第二个对象覆盖,出现在双端队列中的第二个对象现在为空。所以显然某处存在错误,它必须是在调用 emplace_back 期间修改 deque 的未定义行为,或者 libc++ 没有完成它的工作.是哪一个?

最佳答案

正如 Howard Hinnant 回答的那样 on the bug report ,标准没有说明这种情况,但需要说明这将导致未定义的行为:

In each case, because of exception safety considerations, the container is not "altered" until the construction of a foo is complete. That way, if the foo constructor throws, the container state is unchanged. For example vector.size() is not altered until the foo constructor is complete. Therefore when the second construction starts before the first one is complete, it is still appending to a zero-length vector.

This is not an issue that can be addressed in the implementation of the containers. The standard needs to say "don't do that."

所以不要指望它能与任何实现一起工作。

关于c++ - 在调用 emplace_back 期间修改 std::deque 是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16955265/

相关文章:

c++ - 为什么可以将 const char* 分配给 char*?

c++ - 填充矩形并在 opengl 中应用非零缠绕规则

c++ - 无法在 C++ 中通过自动迭代映射

c++ - C++11 lambdas 如何表示和传递?

c++ - 大括号初始化时 GCC 出现编译错误

c++ - 将 block 从 Objective-C 传递给 C++ 方法

c++ - 是否可以从适应的结构生成融合图?

c++ - c_str() 与 std::string - 这段小代码的真正区别是什么?

c - 对于浮点宏,C 标准的 "converted to its semantic type"是什么意思?

c++ - 演绎指南是否需要 noexcept 说明符?