拷貝構造函數
簡單的說就是——用一個對象構造另外一個對象
class Myclass
{public:int d=0;Myclass(int d_){d = d_}; //常用的構造函數Myclass(Myclass c) //拷貝構造函數{d = c.d;}
};
//對比
class Myclass
{public:int d=0;Myclass(int d_){d = d_}; //常用的構造函數Myclass(const Myclass& c) //高效安全的拷貝構造函數{d = c.d;}
};
//調用
int main()
{Myclass A(3);Myclass B(A);
}
簡單的說一下,main中展示了兩種構造對象的方式:
一種是用了一般構造函數,構造了對象A
一種是用了拷貝構造函數,利用A構造了對象B
這里注意一下,對比 展示了拷貝構造函數的寫法,后者傳入參數用了常引用,避免了一次形參到實參的拷貝,同時const保護了A在函數內不被意外修改。
左值右值(會轉換)
左值:c++中可以取地址的,有名字的。
右值: 不可取地址,無名字
左值k變右值:std::move(k);
移動構造函數
先給一個簡單的例子
class A
{public:int* a;A(){a=new int(2);}//普通的構造函數A(A&& a_out){a = a_out.a;a_out.a =nullptr;}//移動構造A(const A& c_){a = c_.a;c_.a = nullptr;};//拷貝構造~A(){if(a!=nullptr)delete a;}//析構函數
};
int main()
{A k = A();A ak = k; A ck = std::move(ak);
}
這里A&& 類型我們稱為右值引用。
A k = A();顯然 A() 先調用了普通的構造函數,然而由于是個右值(因為沒有變量)。用來初始化k對象,這里就調用了移動構造
我們利用左值k來初始化ak對象,顯然就是拷貝構造。
最后雖然ak是左值,但是move運算后得到右值,所以也是移動構造。
單例模式——懶漢模式(只有在調用的時候才初始化)
class Singletem
{public:static Singletem& getitem(){static Singletem it;return it;} Singletem(const Singletem & itt) = delete;//禁用拷貝構造;Singletem(Singletem && itt) = delete;//禁用移動構造Singletem& operator=(const Singletem & itt) = delete; //禁用拷貝賦值運算符//例如 Singletem A; Singletem B;// A = B;Singletem& operator=(Sinletem&& itt) = delete;//禁用移動賦值運算符 //例如 Singletem A;// A = Singletem();private:Singletem();
};
或者寫作
class noncopyable
{
protected:noncopyable() = default;~noncopyable() = default;noncopyable(const noncopyable & itt) = delete;//禁用拷貝構造;noncopyable(noncopyable && itt) = delete;//禁用移動構造noncopyable& operator=(const noncopyable & itt) = delete; //禁用拷貝賦值運算符noncopyable& operator=(noncopyable&& itt) = delete;//禁用移動賦值運算符
}
class Singletem:noncopyable
{public:static Singletem& getitem(){static Singletem it;return it;} private:Singletem();
};
這里有一個小細節,operator返回的是引用,這是為了鏈式法則,例如a=b=2;
單例模式——餓漢模式(未經調用就先初始化)
class Singletem:noncopyable
{public:static Singletem& getitem(){static Singletem it;return it;} private:static Singletem tem;Singletem();
};
Singletem Singletem::tem;//實例初始化
int main()
{
Singletem s1 = Singletem::getitem();
Singletem s2 = Singletem::getitem();
bool c= &s1==&s2;
return 1;
}