C++|構造與複製操作的淺拷貝、深拷貝、轉移行為

當用戶自定義類型含有指針成員且其指向堆內存時,當存在複製構造和對象複製操作時,如果是淺拷貝,則會存在多個指針指向同一塊堆內存的問題,這時無法在恰當的時機由某一對象進行delete操作,所以需要做深拷貝,但深拷貝存在效率低下的問題,因為每一次深拷貝都需要建立臨時對象,臨時對象需要進行構造與析構,如果將臨時對象持久化,則可以解決效率問題,這就是所謂的轉移(move)語義(C++11)。所以,我們通常有三種選擇:

1 提供深拷貝行為,由編譯器提供默認的轉移行為(轉移構造或轉移賦值);

2 禁掉拷貝行為,提供或不提供定製的轉移行為;

3 既提供深拷貝行為,也提供定製的轉移行為;

<code>#include <iostream>
using namespace std;

struct MyPtr
{
explicit MyPtr(int value) // 構造
:ptr(new int(value)){}
explicit MyPtr(MyPtr const& other) // 深拷貝構造
:ptr(new int(*other.ptr)){}
//MyPtr(MyPtr const&)=delete; // 禁用拷貝構造

//MyPtr(MyPtr const& other) // 淺拷貝
//:ptr(other.ptr){}

MyPtr(MyPtr&& other) // 轉移構造
:ptr(other.ptr)
{
other.ptr = nullptr;
}
/*
轉移構造與淺拷貝區別:
兩者都是僅複製指針成員的指向。但是轉移構造多了一步讓源指針置空的操作,
也就是所謂的資源所有權轉移,讓新對象獨佔源對象中指針成員所指向的內存。
這樣不會造成新舊對象中的指針成員指向同一塊內存

*/
MyPtr& operator=(MyPtr const& other) // 賦值操作符重載
{
if(ptr!=other.ptr)
{
delete ptr;
ptr = new int(*other.ptr);
//*ptr=*other.ptr;
}
return *this;
}
//MyPtr& operator=(MyPtr const&)=delete; // 禁用賦值操作符重載
MyPtr& operator=(MyPtr&& other) // 轉移賦值
{
if(ptr!=other.ptr)
{
ptr=other.ptr;
other.ptr=nullptr;
}
return *this;
}

~MyPtr(){delete ptr;}
int* ptr;
};

int main()
{

MyPtr src(31);
MyPtr dst_cpy(src);
cout< cout< //MyPtr dst_move(static_cast<myptr>(src));
MyPtr dst_move(std::move(src));
cout< cout< system("pause");
return 0;
}
//output: 31 0 31 1/<myptr>/<iostream>/<code>

-End-


分享到:


相關文章: