📜  使用示例移动C ++中的构造方法

📅  最后修改于: 2021-06-01 01:03:59             🧑  作者: Mango

先决条件: C++中的l值和r值引用,C++中的复制构造函数。

什么是Move构造函数?

C++中的复制构造函数使用l值引用和复制语义(复制语义意味着将对象的实际数据复制到另一个对象,而不是使另一个对象指向堆中已经存在的对象)。当移动构造函数处理r值引用并移动语义时(移动语义涉及指向内存中已经存在的对象)。

在声明新对象并为其分配r值时,首先创建一个临时对象,然后使用该临时对象将值分配给该对象。因此,复制构造函数被调用了几次,从而增加了开销并降低了代码的计算能力。为了避免这种开销并提高代码效率,我们使用move构造函数。

为什么要使用Move构造函数?

Move构造函数移动堆中的资源,即,与复制构造函数不同,Copy构造函数将现有对象的数据复制并分配给新对象,而move构造函数只是使已声明对象的指针指向临时对象的数据,而使该对象无效临时对象的指针。因此,移动构造函数可防止不必要地在内存中复制数据。

移动构造函数的工作有点类似于默认的成员明智的复制构造函数,但是在这种情况下,它使临时对象的指针为空,从而防止多个对象指向同一内存位置。

以下是未声明move构造函数的程序:

C++
// C++ program without declaring the
// move constructor
#include 
#include 
using namespace std;
 
// Move Class
class Move {
private:
    // Declaring the raw pointer as
    // the data member of the 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 to delegated
    // Copy constructor
    Move(const Move& source)
        : Move{ *source.data }
    {
 
        // Copying constructor copying
        // the data by making deep copy
        cout << "Copy Constructor is called - "
             << "Deep copy for "
             << *source.data
             << endl;
    }
 
    // Destructor
    ~Move()
    {
        if (data != nullptr)
 
            // If the pointer is not
            // pointing to nullptr
            cout << "Destructor is called for "
                 << *data << endl;
        else
 
            // If the pointer is
            // pointing to nullptr
            cout << "Desturctor is called"
                 << " for nullptr"
                 << endl;
 
        // Free the memory assigned to
        // data member of the object
        delete data;
    }
};
 
// Driver Code
int main()
{
    // Create vector of Move Class
    vector vec;
 
    // Inserting object of Move class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}


C++
// C++ program with declaring the
// move constructor
#include 
#include 
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 }
    {
 
        // Copying the data by making
        // deep copy
        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)
 
            // If pointer is not pointing
            // to nullptr
            cout << "Destructor is called for "
                 << *data << endl;
        else
 
            // If pointer is pointing
            // to nullptr
            cout << "Destructor is called"
                 << " for nullptr "
                 << endl;
 
        // Free up the memory assigned to
        // The data member of the object
        delete data;
    }
};
 
// Driver Code
int main()
{
    // Vector of Move Class
    vector vec;
 
    // Inserting Object of Move Class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}


输出:
Constructor is called for 10
Constructor is called for 10
Copy Constructor is called - Deep copy for 10
Destructor is called for 10
Constructor is called for 20
Constructor is called for 20
Copy Constructor is called - Deep copy for 20
Constructor is called for 10
Copy Constructor is called - Deep copy for 10
Destructor is called for 10
Destructor is called for 20
Destructor is called for 10
Destructor is called for 20

解释:
上面的程序显示了不必要的调用复制构造函数,并且通过在每次调用复制构造函数时将相同数据多次复制为新对象,从而低效地使用了内存。

Move构造函数的语法:

Object_name(Object_name&& obj) 
   : data{ obj.data }
{
   // Nulling out the pointer to the temporary data
   obj.data = nullptr;
}

通过使用move构造函数可以避免不必要的内存使用。以下是声明move构造函数的程序:

C++

// C++ program with declaring the
// move constructor
#include 
#include 
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 }
    {
 
        // Copying the data by making
        // deep copy
        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)
 
            // If pointer is not pointing
            // to nullptr
            cout << "Destructor is called for "
                 << *data << endl;
        else
 
            // If pointer is pointing
            // to nullptr
            cout << "Destructor is called"
                 << " for nullptr "
                 << endl;
 
        // Free up the memory assigned to
        // The data member of the object
        delete data;
    }
};
 
// Driver Code
int main()
{
    // Vector of Move Class
    vector vec;
 
    // Inserting Object of Move Class
    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });
    return 0;
}

输出:

Constructor is called for 10
Move Constructor for 10
Destructor is called for nullptr 
Constructor is called for 20
Move Constructor for 20
Constructor is called for 10
Copy Constructor is called -Deep copy for 10
Destructor is called for 10
Destructor is called for nullptr 
Destructor is called for 10
Destructor is called for 20

解释:
通过对move构造函数进行调用,可以避免对copy构造函数进行不必要的调用。因此,使代码的内存使用效率更高,并减少了调用move构造函数的开销。

想要从精选的最佳视频中学习并解决问题,请查看有关从基础到高级C++的C++基础课程以及有关语言和STL的C++ STL课程。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”