c++ 我不明白为什么复制构造函数(粗体显示)在下面的例子中被调用?谁能解释一下为什么我得到下面的输出?

pcww981p  于 2023-01-14  发布在  其他
关注(0)|答案(2)|浏览(93)
#include <iostream>
#include <vector>
using namespace std;

// Move Class
class Move {
private:
    // Declare the raw pointer as
    // the data member of class
    int* data;

public:

    // Constructor
    Move(int d)
    {
        // Declare object in the heap
        data = new int;
        *data = d;
        cout << "Constructor is called for "
            << d << endl;
    };

    // Copy Constructor
    Move(const Move& source)
        : Move{ *source.data }
    {
        cout << "Copy Constructor is called -"
            << "Deep copy for "
            << *source.data
            << endl;
    }

    // Move Constructor
    Move(Move&& source)
        : data{ source.data }
    {

        cout << "Move Constructor for "
            << *source.data << endl;
        source.data = nullptr;
    }

    // Destructor
    ~Move()
    {
        if (data != nullptr)
            cout << "Destructor is called for "
                << *data << endl;
        else
            cout << "Destructor is called"
                << " for nullptr "
                << endl;
        delete data;
    }
};

// Driver Code
int main()
{
    // Vector of Move Class
    vector<Move> vec;

    // Inserting Object of Move Class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}

输出:
构造函数被调用10
移动10的构造函数
为nullptr调用析构函数
构造函数被调用20
移动建造者20

    • 为10调用构造函数

调用复制构造函数-10的深度复制**调用10的析构函数
为nullptr调用析构函数
为10调用析构函数
析构函数被调用20

omtl5h9j

omtl5h9j1#

我想你要问的是为什么调用复制构造函数而不是移动构造函数?因为你的移动构造函数不是noexcept,如果你把它标记为noexcept,那么在重分配的时候就会使用移动构造函数。
有关详细信息,请参阅此相关答案:https://stackoverflow.com/a/47017784/6324364
通常的建议是move构造函数应该尽可能地为noexcept。许多标准库函数不会使用可能抛出异常的move构造函数。

8i9zcol2

8i9zcol22#

向量是作为一个整体存储在内存中的,当你把第二个元素加到向量上时,它的当前内存需要扩展以容纳新添加的元素。这将要求您将现有元素复制到分配了足够内存以容纳这两个元素的其他位置(在您的例子中)第一个和第二个元素。看看reserve正在做什么,以及您如何从中受益。或者,类似地,如果您的向量是固定大小的,您也可以看看array

相关问题