是什么解释了这段代码中如此多的移动和破坏

What explains so many moves and destructions in this snippet

为了理解五法则,我想到了这个:

#include <iostream>
#include <vector>

class A
{
public:
A(int y)
{
    std::cout << "constructed\n";
    x = new int[y];
}
~A()
{
    std::cout << "destructed\n";
    delete[] x;
}
A(const A &other)
{
    std::cout << "copied\n";
    if (other.x != nullptr)
        x = new int[sizeof(other.x) / sizeof(other.x[0])];
}
A(A && other) :
    x(other.x)
{
    std::cout << "moved\n";
    other.x = nullptr;
}
A& operator=(A other)
{
    std::cout << "assignments\n";
    std::swap(x, other.x);
    return *this;
}
int *x;
};

class B
{
private:
std::vector<A> a;
public:
B()
{
    for (int i = 0; i < 5; i++)
        a.emplace_back(A(1));
    std::cout << "----------------------\n";
    for (int i = 0; i < 5; i++)
        a.push_back({ 2 });
}
};

int main()
{
B *b = new B();
std::cin.get();
}

如果我使用 emplace_back 和 push_back 各 1 次,我将得到以下输出,而不管我调用每个方法的顺序如何:

constructed
moved
destructed
----------------------
constructed
moved
destructed
moved
destructed

我接受。但是,如果我使用上面写的代码,我会得到一些棘手的模式:

constructed
moved
destructed
constructed
moved
destructed
moved
destructed
constructed
moved
moved
destructed
destructed
moved
destructed
constructed
moved
moved
moved
destructed
destructed
destructed
moved
destructed
constructed
moved
moved
moved
moved
destructed
destructed
destructed
destructed
moved
destructed
----------------------
constructed
moved
destructed
constructed
moved
moved
moved
moved
moved
moved
destructed
destructed
destructed
destructed
destructed
destructed
moved
destructed
constructed
moved
destructed
constructed
moved
destructed
constructed
moved
moved
moved
moved
moved
moved
moved
moved
moved
destructed
destructed
destructed
destructed
destructed
destructed
destructed
destructed
destructed
moved
destructed

为什么要解释这么多 "moved" 和 "destructed"?另外,我们是否可以仅通过此输出来说明 emplace_back 优于 push_back?

我认为这个输出不是错误

如果std::vector的大小已满并且您尝试推送,vector将分配更多内存并将原始内存块中的对象移动到新内存块并销毁原始内存块。

所以 你可以使用 std::vector.reserve()

#include <iostream>
#include <vector>

class A
{
public:
A(int y)
{
    std::cout << "constructed\n";
    x = new int[y];
}
~A()
{
    std::cout << "destructed\n";
    delete[] x;
}
A(const A &other)
{
    std::cout << "copied\n";
    if (other.x != nullptr)
        x = new int[sizeof(other.x) / sizeof(other.x[0])];
}
A(A && other) :
    x(other.x)
{
    std::cout << "moved\n";
    other.x = nullptr;
}
A& operator=(A other)
{
    std::cout << "assignments\n";
    std::swap(x, other.x);
    return *this;
}
int *x;
};

class B
{
private:
std::vector<A> a;
public:
B()
{
    //reserve
    a.reserve(5);

    for (int i = 0; i < 5; i++)
        a.emplace_back(A(1));
    std::cout << "----------------------\n";
   // for (int i = 0; i < 5; i++)
   //    a.push_back({ 2 });
}
};

int main()
{
B *b = new B();
std::cin.get();
}

这个输出会是这样的

constructed
moved
destructed
constructed
moved
destructed
constructed
moved
destructed
constructed
moved
destructed
constructed
moved
destructed