最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++中對(duì)構(gòu)造函數(shù)和賦值運(yùn)算符的復(fù)制和移動(dòng)操作

 更新時(shí)間:2016年01月21日 16:58:11   投稿:goldensun  
這篇文章主要介紹了C++中對(duì)構(gòu)造函數(shù)和賦值運(yùn)算符的復(fù)制和移動(dòng),是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下

復(fù)制構(gòu)造函數(shù)和復(fù)制賦值運(yùn)算符
從 C++ 11 中開(kāi)始,該語(yǔ)言支持兩種類型的分配:復(fù)制賦值和移動(dòng)賦值。 在本文中,“賦值”意味著復(fù)制賦值,除非有其他顯式聲明。 賦值操作和初始化操作都會(huì)導(dǎo)致對(duì)象被復(fù)制。
賦值:在將一個(gè)對(duì)象的值賦給另一個(gè)對(duì)象時(shí),第一個(gè)對(duì)象將復(fù)制到第二個(gè)對(duì)象中。 因此,

Point a, b;
...
a = b;

導(dǎo)致 b 的值被復(fù)制到 a 中。
初始化:在以下情況下將進(jìn)行初始化:聲明新對(duì)象、參數(shù)通過(guò)值傳遞給函數(shù)或值通過(guò)值從函數(shù)返回。
您可以為類類型的對(duì)象定義“復(fù)制”的語(yǔ)義。 例如,考慮此代碼:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

前面的代碼可能表示“將 FILE1.DAT 的內(nèi)容復(fù)制到 FILE2.DAT”,也可能表示“忽略 FILE2.DAT 并使 b 成為 FILE1.DAT 的另一個(gè)句柄”。 您必須將適當(dāng)?shù)膹?fù)制語(yǔ)義附加到每個(gè)類,如下所示。
通過(guò)將賦值運(yùn)算符 operator= 與對(duì)類類型的引用一起用作返回類型和 const 引用所傳遞的參數(shù)(例如,ClassName& operator=(const ClassName& x);)。
通過(guò)通過(guò)復(fù)制構(gòu)造函數(shù)。 有關(guān)復(fù)制構(gòu)造函數(shù)的詳細(xì)信息,請(qǐng)參閱聲明構(gòu)造函數(shù)的規(guī)則。
如果不聲明復(fù)制構(gòu)造函數(shù),編譯器將為你生成 member-wise 復(fù)制構(gòu)造函數(shù)。  如果不聲明復(fù)制賦值運(yùn)算符,編譯器將為你生成 member-wise 復(fù)制賦值運(yùn)算符。 聲明復(fù)制構(gòu)造函數(shù)不會(huì)取消編譯器生成的復(fù)制賦值運(yùn)算符,反之亦然。 如果實(shí)現(xiàn)上述其中一項(xiàng),建議您還實(shí)現(xiàn)另一項(xiàng)以使代碼的含義變得明確。
逐個(gè)成員賦值和初始化 中更詳細(xì)地介紹了逐個(gè)成員賦值。
復(fù)制構(gòu)造函數(shù)采用了 class-name& 類型的參數(shù),其中 class-name 是為其定義構(gòu)造函數(shù)的類的名稱。 例如:

// spec1_copying_class_objects.cpp
class Window
{
public:
 Window( const Window& ); // Declare copy constructor.
 // ...
};

int main()
{
}

說(shuō)明:
盡可能創(chuàng)建該類型的復(fù)制構(gòu)造函數(shù)的參數(shù) const class-name&。 這可防止復(fù)制構(gòu)造函數(shù)意外更改從中復(fù)制它的對(duì)象。 它還支持從 const 對(duì)象進(jìn)行復(fù)制。
編譯器生成的構(gòu)造函數(shù)
編譯器生成的復(fù)制構(gòu)造函數(shù)(如用戶定義的復(fù)制構(gòu)造函數(shù))具有單個(gè)參數(shù)類型“對(duì) class-name 的引用”。 當(dāng)所有基類和成員類都具有聲明為采用 const class-name& 類型的單個(gè)參數(shù)的復(fù)制構(gòu)造函數(shù)時(shí),將引發(fā)異常。 在這種情況下,編譯器生成的復(fù)制構(gòu)造函數(shù)的參數(shù)也是 const。
當(dāng)復(fù)制構(gòu)造函數(shù)的參數(shù)類型不是 const 時(shí),通過(guò)復(fù)制 const 對(duì)象進(jìn)行初始化將產(chǎn)生錯(cuò)誤。 反之則不然:如果參數(shù)是 const,您可以通過(guò)復(fù)制不是 const 的對(duì)象進(jìn)行初始化。
編譯器生成的賦值運(yùn)算符遵循關(guān)于 const 的相同模式。 除非所有基類和成員類中的賦值運(yùn)算符都采用 const class-name& 類型的參數(shù),否則它們將采用 class-name& 類型的單個(gè)參數(shù)。 在這種情況下,類的生成的賦值運(yùn)算符采用 const 參數(shù)。
說(shuō)明:
當(dāng)虛擬基類由復(fù)制構(gòu)造函數(shù)(編譯器生成或用戶定義的)初始化時(shí),將只初始化這些基類一次:在構(gòu)造它們時(shí)。
含義類似于復(fù)制構(gòu)造函數(shù)的含義。 當(dāng)參數(shù)類型不是 const 時(shí),從 const 對(duì)象賦值將產(chǎn)生錯(cuò)誤。 反之則不然:如果將 const 值賦給不是 const 的值,則賦值能成功。

移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符
下面的示例基于用于管理內(nèi)存緩沖區(qū)的 C++ 類 MemoryBlock。

// MemoryBlock.h
#pragma once
#include <iostream>
#include <algorithm>

class MemoryBlock
{
public:

 // Simple constructor that initializes the resource.
 explicit MemoryBlock(size_t length)
  : _length(length)
  , _data(new int[length])
 {
  std::cout << "In MemoryBlock(size_t). length = "
    << _length << "." << std::endl;
 }

 // Destructor.
 ~MemoryBlock()
 {
  std::cout << "In ~MemoryBlock(). length = "
    << _length << ".";

  if (_data != nullptr)
  {
   std::cout << " Deleting resource.";
   // Delete the resource.
   delete[] _data;
  }

  std::cout << std::endl;
 }

 // Copy constructor.
 MemoryBlock(const MemoryBlock& other)
  : _length(other._length)
  , _data(new int[other._length])
 {
  std::cout << "In MemoryBlock(const MemoryBlock&). length = " 
    << other._length << ". Copying resource." << std::endl;

  std::copy(other._data, other._data + _length, _data);
 }

 // Copy assignment operator.
 MemoryBlock& operator=(const MemoryBlock& other)
 {
  std::cout << "In operator=(const MemoryBlock&). length = " 
    << other._length << ". Copying resource." << std::endl;

  if (this != &other)
  {
   // Free the existing resource.
   delete[] _data;

   _length = other._length;
   _data = new int[_length];
   std::copy(other._data, other._data + _length, _data);
  }
  return *this;
 }

 // Retrieves the length of the data resource.
 size_t Length() const
 {
  return _length;
 }

private:
 size_t _length; // The length of the resource.
 int* _data; // The resource.
};

以下過(guò)程介紹如何為示例 C++ 類編寫(xiě)移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符。
為 C++ 創(chuàng)建移動(dòng)構(gòu)造函數(shù)
定義一個(gè)空的構(gòu)造函數(shù)方法,該方法采用一個(gè)對(duì)類類型的右值引用作為參數(shù),如以下示例所示:

MemoryBlock(MemoryBlock&& other)
 : _data(nullptr)
 , _length(0)
{
}

在移動(dòng)構(gòu)造函數(shù)中,將源對(duì)象中的類數(shù)據(jù)成員添加到要構(gòu)造的對(duì)象:

_data = other._data;
_length = other._length;

將源對(duì)象的數(shù)據(jù)成員分配給默認(rèn)值。 這樣可以防止析構(gòu)函數(shù)多次釋放資源(如內(nèi)存):

other._data = nullptr;
other._length = 0;

為 C++ 類創(chuàng)建移動(dòng)賦值運(yùn)算符
定義一個(gè)空的賦值運(yùn)算符,該運(yùn)算符采用一個(gè)對(duì)類類型的右值引用作為參數(shù)并返回一個(gè)對(duì)類類型的引用,如以下示例所示:

MemoryBlock& operator=(MemoryBlock&& other)
{
}

在移動(dòng)賦值運(yùn)算符中,如果嘗試將對(duì)象賦給自身,則添加不執(zhí)行運(yùn)算的條件語(yǔ)句。

if (this != &other)
{
}

在條件語(yǔ)句中,從要將其賦值的對(duì)象中釋放所有資源(如內(nèi)存)。
以下示例從要將其賦值的對(duì)象中釋放 _data 成員:

// Free the existing resource.
delete[] _data;

執(zhí)行第一個(gè)過(guò)程中的步驟 2 和步驟 3 以將數(shù)據(jù)成員從源對(duì)象轉(zhuǎn)移到要構(gòu)造的對(duì)象:

// Copy the data pointer and its length from the 
// source object.
_data = other._data;
_length = other._length;

// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;

返回對(duì)當(dāng)前對(duì)象的引用,如以下示例所示:

return *this;

以下示例顯示了 MemoryBlock 類的完整移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符:

// Move constructor.
MemoryBlock(MemoryBlock&& other)
 : _data(nullptr)
 , _length(0)
{
 std::cout << "In MemoryBlock(MemoryBlock&&). length = " 
    << other._length << ". Moving resource." << std::endl;

 // Copy the data pointer and its length from the 
 // source object.
 _data = other._data;
 _length = other._length;

 // Release the data pointer from the source object so that
 // the destructor does not free the memory multiple times.
 other._data = nullptr;
 other._length = 0;
}

// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other)
{
 std::cout << "In operator=(MemoryBlock&&). length = " 
    << other._length << "." << std::endl;

 if (this != &other)
 {
  // Free the existing resource.
  delete[] _data;

  // Copy the data pointer and its length from the 
  // source object.
  _data = other._data;
  _length = other._length;

  // Release the data pointer from the source object so that
  // the destructor does not free the memory multiple times.
  other._data = nullptr;
  other._length = 0;
 }
 return *this;
}

以下示例演示移動(dòng)語(yǔ)義如何能提高應(yīng)用程序的性能。此示例將兩個(gè)元素添加到一個(gè)矢量對(duì)象,然后在兩個(gè)現(xiàn)有元素之間插入一個(gè)新元素。在 Visual C++ 2010 中,vector 類使用移動(dòng)語(yǔ)義,通過(guò)移動(dòng)矢量元素(而非復(fù)制它們)來(lái)高效地執(zhí)行插入操作。

// rvalue-references-move-semantics.cpp
// compile with: /EHsc
#include "MemoryBlock.h"
#include <vector>

using namespace std;

int main()
{
 // Create a vector object and add a few elements to it.
 vector<MemoryBlock> v;
 v.push_back(MemoryBlock(25));
 v.push_back(MemoryBlock(75));

 // Insert a new element into the second position of the vector.
 v.insert(v.begin() + 1, MemoryBlock(50));
}

該示例產(chǎn)生下面的輸出:

In MemoryBlock(size_t). length = 25.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 75.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(MemoryBlock&&). length = 75. Moving resource.
In ~MemoryBlock(). length = 0.
In MemoryBlock(size_t). length = 50.
In MemoryBlock(MemoryBlock&&). length = 50. Moving resource.
In MemoryBlock(MemoryBlock&&). length = 50. Moving resource.
In operator=(MemoryBlock&&). length = 75.
In operator=(MemoryBlock&&). length = 50.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.

使用移動(dòng)語(yǔ)義的此示例版本比不使用移動(dòng)語(yǔ)義的版本更高效,因?yàn)榍罢邎?zhí)行的復(fù)制、內(nèi)存分配和內(nèi)存釋放操作更少。
可靠編程
若要防止資源泄漏,請(qǐng)始終釋放移動(dòng)賦值運(yùn)算符中的資源(如內(nèi)存、文件句柄和套接字)。
若要防止不可恢復(fù)的資源損壞,請(qǐng)正確處理移動(dòng)賦值運(yùn)算符中的自我賦值。
如果為您的類同時(shí)提供了移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符,則可以編寫(xiě)移動(dòng)構(gòu)造函數(shù)來(lái)調(diào)用移動(dòng)賦值運(yùn)算符,從而消除冗余代碼。以下示例顯示了調(diào)用移動(dòng)賦值運(yùn)算符的移動(dòng)構(gòu)造函數(shù)的修改后的版本:

// Move constructor.
MemoryBlock(MemoryBlock&& other)
 : _data(nullptr)
 , _length(0)
{
 *this = std::move(other);
}

相關(guān)文章

  • OpenCV圖像處理之常見(jiàn)的圖像灰度變換

    OpenCV圖像處理之常見(jiàn)的圖像灰度變換

    這篇文章主要介紹了OpenCV圖像處理之常見(jiàn)的圖像灰度變換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • C++算法設(shè)計(jì)之馬踏棋盤的實(shí)現(xiàn)

    C++算法設(shè)計(jì)之馬踏棋盤的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了C++算法設(shè)計(jì)之馬踏棋盤的實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解C++中普通舊數(shù)據(jù)(POD)的使用

    詳解C++中普通舊數(shù)據(jù)(POD)的使用

    普通舊數(shù)據(jù)就是內(nèi)存中的連續(xù)字節(jié)序列,是能夠被“僅當(dāng)作數(shù)據(jù)”處理的對(duì)象。這篇文章主要帶大家了解一下C++中普通舊數(shù)據(jù)的定義與使用,感興趣的可以了解下
    2023-03-03
  • 實(shí)例分享cmake編譯一個(gè)簡(jiǎn)單c++項(xiàng)目(demo)

    實(shí)例分享cmake編譯一個(gè)簡(jiǎn)單c++項(xiàng)目(demo)

    下面通過(guò)一個(gè)小例子來(lái)說(shuō)明cmake編譯一個(gè)c++項(xiàng)目,生成可執(zhí)行文件,需要的朋友可以參考下
    2020-02-02
  • C++實(shí)現(xiàn)企業(yè)職工工資管理系統(tǒng)

    C++實(shí)現(xiàn)企業(yè)職工工資管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)企業(yè)職工工資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C++ move()函數(shù)案例詳解

    C++ move()函數(shù)案例詳解

    這篇文章主要介紹了C++ move()函數(shù)案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • C語(yǔ)言實(shí)現(xiàn)電話簿項(xiàng)目

    C語(yǔ)言實(shí)現(xiàn)電話簿項(xiàng)目

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電話簿項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 最新評(píng)論

    天镇县| 黄山市| 永福县| 广丰县| 泰顺县| 当雄县| 香河县| 晋江市| 阿瓦提县| 仙桃市| 安吉县| 北流市| 沾益县| 呼伦贝尔市| 左贡县| 游戏| 林甸县| 邵东县| 武威市| 兴海县| 临猗县| 嘉定区| 青田县| 迭部县| 高雄市| 元谋县| 安福县| 宁津县| 罗江县| 鹿邑县| 南汇区| 和田县| 澄江县| 南阳市| 包头市| 且末县| 衡东县| 大连市| 锦屏县| 鸡东县| 井研县|