用在别处创建的对象填充 std::vector

MrE*_*een 12 c++ vector move-semantics

我正在尝试std::vector使用在函数中创建的对象填充 a ,如下所示:

class Foo
{
public:
   Foo() { std::cout << "Foo created!\n"; }
   Foo(const Foo& other) { std::cout << "Foo copied!\n"; }
   Foo(Foo&& other) { std::cout << "Foo moved\n"; }
   ~Foo() { std::cout << "Foo destroyed\n"; }
};

static Foo createFoo() 
{
   return Foo();
}

int main()
{
   {
       std::vector<Foo> fooVector;
       fooVector.reserve(2);
       fooVector.push_back(createFoo());
       fooVector.push_back(createFoo());
       std::cout << "reaching end of scope\n";
   }
   std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)

输出:

Foo created!
Foo moved
Foo destroyed
Foo created!
Foo moved
Foo destroyed
reaching end of scope
Foo destroyed
Foo destroyed
Run Code Online (Sandbox Code Playgroud)

怎么会Foo被破坏的次数多于被创造的次数?我不明白这里发生了什么,我以为Foo会被复制,但没有触发复制构造函数。

std::vector用在其他地方创建的对象填充而不被销毁的最佳方法是什么?

eer*_*ika 14

Foo 如何被销毁的次数比它被创建的次数多?

输出显示了与显示破坏一样多的创建:

            change -> cumulative total    
Foo created!    +1 -> 1
Foo moved       +1 -> 2
Foo destroyed   -1 -> 1
Foo created!    +1 -> 2
Foo moved       +1 -> 3
Foo destroyed   -1 -> 2
reaching end of scope
Foo destroyed   -1 -> 1
Foo destroyed   -1 -> 0 all objects that were created are now destroyed
Run Code Online (Sandbox Code Playgroud)

我以为 Foo 会被复制,但没有触发复制构造函数。

每次将右值传递给构造函数时。这就是为什么使用移动构造函数而不是复制构造函数的原因。


用在其他地方创建的对象填充 std::vector 而不破坏它们的最佳方法是什么?

好吧,不要破坏你在别处创建的对象......但通常你应该避免这样做,因为它通常是内存泄漏。

如果您在别处创建两个对象并在向量中创建两个对象,那么您最终会创建 4 个对象。如果你只想要两个对象,那么例如直接在向量中创建对象而不是其他地方。像这样例如:

fooVector.emplace_back();
fooVector.emplace_back();
Run Code Online (Sandbox Code Playgroud)


Nat*_*ica 8

当你做

fooVector.push_back(createFoo());
Run Code Online (Sandbox Code Playgroud)

首先createFoo()创建一个临时Foo对象,这就是为什么你看到

Foo created!
Run Code Online (Sandbox Code Playgroud)

然后,该对象被“移动”到向量中,因为它是一个纯右值。这就是为什么你看到

Foo moved
Run Code Online (Sandbox Code Playgroud)

现在你在向量中有一个对象,但你也有创建的临时对象,移动并没有摆脱那个对象,它只是将其内部移动到向量中的对象中。一旦超出范围,您仍然需要销毁该对象,这发生在完整表达式的末尾,为您提供

Foo destroyed
Run Code Online (Sandbox Code Playgroud)

输出。