将元素推入 std::queue 时避免复制

kee*_*lar 6 c++ stl move c++11

我是 c++11 的新手,希望有一个std::queue存储类的实例,X并尽量避免推送操作中不必要的副本。在 c++11 中,我发现push()有一个右值参考版本:

void push (value_type&& val);
Run Code Online (Sandbox Code Playgroud)

下面的实现也避免了不必要的副本 X

std::queue<X> my_queue;

for (...) { // some for loop
  X x;
  ... // some initialization of x
  my_queue.push(std::move(x));
}
Run Code Online (Sandbox Code Playgroud)

与以下幼稚的实现相比?

std::queue<X> my_queue;

for (...) { // some for loop
  X x;
  ... // some initialization of x
  my_queue.push(x);
}
Run Code Online (Sandbox Code Playgroud)

bob*_*bah 5

自己回答此类问题的最佳方法是创建一个探测对象。

#include <iostream>
struct probe {
    probe() { std::cout << "probe()" << ((void*)this) << std::endl; }
    probe(const probe&) { std::cout << "probe(c&)" << ((void*)this) << std::endl; }
    probe(probe&&) { std::cout << "probe(&&)" << ((void*)this) << std::endl; }
    ~probe() { std::cout << "~probe()" << ((void*)this) << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)

并在测试中使用它代替 X。

我在这里创建了一个游乐场。

当您std::move单独执行任何操作时,是否执行任何额外副本取决于您在右值引用构造函数中键入的内容。


小智 2

当且仅当 X 支持移动语义时,第一个就可以了。

X 可能是这样的:

struct X {
    int value;
    X() {
        static int n;
        value = ++n;
    }

    X(X&&) = default;
    X& operator = (X&&) = default;

    X(const X&) = delete;
    X& operator = (const X&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

注意:此处不允许 X 的副本。