一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

C++之構(gòu)造與析構(gòu)

 山峰云繞 2023-04-17 發(fā)布于貴州

https://www.toutiao.com/article/7221780830300160527/?log_from=e246e008cd46d_1681705879867


       (構(gòu)造函數(shù)是用來初始化對象的特殊成員函數(shù)它們的名稱與類的名稱相同一個(gè)類可以有多個(gè)構(gòu)造函數(shù)以便在創(chuàng)建對象時(shí)使用不同的參數(shù)列表)


C++構(gòu)造函數(shù)

C++構(gòu)造函數(shù)| 構(gòu)造函數(shù)基礎(chǔ)

https://www.toutiao.com/article/7221780830300160527/?log_from=e246e008cd46d_1681705879867

C++中的構(gòu)造函數(shù)是用來初始化對象的特殊成員函數(shù),它們的名稱與類的名稱相同。構(gòu)造函數(shù)在創(chuàng)建類的新對象時(shí)自動(dòng)調(diào)用,用于對對象進(jìn)行初始化工作,比如給屬性賦初值。一個(gè)類可以有多個(gè)構(gòu)造函數(shù),以便在創(chuàng)建對象時(shí)使用不同的參數(shù)列表。所以構(gòu)造函數(shù)的長相決定了對象的長相,無參構(gòu)造函數(shù),對象無參,一個(gè)參數(shù)構(gòu)造函數(shù),對象一個(gè)參數(shù),以此類推。

構(gòu)造函數(shù)的特點(diǎn):

  • 函數(shù)名與類名相同。

  • 返回值沒有返回類型,包括void。

  • 如果沒有顯式地定義構(gòu)造函數(shù),則編譯器會(huì)生成一個(gè)默認(rèn)的構(gòu)造函數(shù)。如果自己寫了,默認(rèn)的就不存在

  • 構(gòu)造函數(shù)允許被重載

  • 構(gòu)造函數(shù)允許缺省

  • 構(gòu)造函數(shù)不需要自己調(diào)用,在構(gòu)造對象的時(shí)候調(diào)用構(gòu)造函數(shù)

如下測試代碼

#include <iostream>
#include <string>
class GirlFriend {

public:
  GirlFriend(std::string name, int age) 
  {
    m_name = name;
    m_age = age;
    std::cout << "兩個(gè)參數(shù):構(gòu)造函數(shù)" << std::endl;
  }
  void print() 
  {
    std::cout << m_name<<"\t"<< m_age << std::endl;
  }
protected:
  std::string m_name;
private:
  int m_age;
};
int main()
{
  //錯(cuò)誤沒有一個(gè)參數(shù)的構(gòu)造函數(shù)
  //GirlFriend object;
  //1.構(gòu)造對象
  GirlFriend  object("baby", 18);
  object.print();
  //2.new一個(gè)對象
  GirlFriend* p = new GirlFriend("小芳", 29);
  p->print();
  
  //3.隱式轉(zhuǎn)換創(chuàng)建,必須具備兩個(gè)參數(shù)構(gòu)造函數(shù)
  GirlFriend girl = { "小美",28 };
  girl.print();
  return 0;
}

結(jié)構(gòu)體中包含構(gòu)造函數(shù),也是一樣的規(guī)則,不能再使用C語言的方式去創(chuàng)建結(jié)構(gòu)體變量。

C++構(gòu)造函數(shù)| explicit 禁止隱式轉(zhuǎn)換

在C++中,關(guān)鍵字explicit通常用于構(gòu)造函數(shù)聲明。使用explicit關(guān)鍵字可以防止隱式轉(zhuǎn)換,以便只有顯式調(diào)用才能將單個(gè)參數(shù)構(gòu)造函數(shù)作為隱式轉(zhuǎn)換執(zhí)行。如下測試代碼

#include <iostream>
#include <string>
class GirlFriend {

public:
  explicit GirlFriend(std::string name, int age) 
  {
    m_name = name;
    m_age = age;
  }
  void print() 
  {
    std::cout << m_name<<"\t"<< m_age << std::endl;
  }
protected:
  std::string m_name;
private:
  int m_age;
};
int main()
{
  //錯(cuò)誤:禁止隱式轉(zhuǎn)換
  //GirlFriend girl = { "小美",28 };
  GirlFriend girl("小美", 28);
  girl.print();
  return 0;
}

C++構(gòu)造函數(shù)| delete與default

在C++類中, deletedefault都是關(guān)鍵字。

  • delete 關(guān)鍵字在類中用于刪除特殊成員函數(shù)、釋放動(dòng)態(tài)分配的內(nèi)存。

  • default 關(guān)鍵字用于使用類中默認(rèn)的函數(shù)

如下測試代碼

#include <iostream>
#include <string>
class GirlFriend {

public:
  //刪掉默認(rèn)構(gòu)造函數(shù)
  GirlFriend() = delete;
protected:

};

class BoyFriend {

public:
  //使用默認(rèn)的構(gòu)造函數(shù),故可以創(chuàng)建無參對象
  BoyFriend() = default;
  BoyFriend(int age) {}
protected:

};
int main()
{
  //錯(cuò)誤,默認(rèn)構(gòu)造函數(shù)被刪除,不存在構(gòu)造函數(shù),無法創(chuàng)建對象
  //GirlFriend girl;
  //調(diào)用默認(rèn)函數(shù)構(gòu)造無參對象
  BoyFriend boy;
  BoyFriend moying(18);
  return 0;
}

C++構(gòu)造函數(shù)| 構(gòu)造函數(shù)委托

在C++11中,我們可以使用構(gòu)造函數(shù)委托來簡化類的構(gòu)造函數(shù)。構(gòu)造函數(shù)委托可以讓一個(gè)構(gòu)造函數(shù)調(diào)用另一個(gè)構(gòu)造函數(shù)來完成部分或全部的初始化工作。調(diào)用方式必須用初始化參數(shù)列表方式。

#include <iostream>
#include <string>
class GirlFriend
{

public:
  GirlFriend(std::string name,int age)
  {
    m_name = name;
    m_age = age;
  }
  //構(gòu)造函數(shù)委托,初始化參數(shù)列表
  GirlFriend() :GirlFriend("默認(rèn)", 0)
  {

  }
  void  print() 
  {
    std::cout << m_name << "\t" << m_age << std::endl;
  }
protected:
  std::string m_name;
  int m_age;
};

int main()
{
  GirlFriend object;
  object.print();
  return 0;
}

C++構(gòu)造函數(shù)| 匿名對象

C++中的匿名對象是指沒有被命名的臨時(shí)對象。匿名對象是一個(gè)右值,引用傳參需要用常引用或者右值引用,它們通常在函數(shù)調(diào)用的時(shí)候被創(chuàng)建,用于傳遞參數(shù)或作為函數(shù)返回值。 匿名對象的生命周期僅限于當(dāng)前表達(dá)式或語句結(jié)束之前,在此之后便會(huì)被銷毀。

以下是一些產(chǎn)生匿名對象的常見方式:

  • 匿名對象充當(dāng)函數(shù)參數(shù)

  • 匿名對象賦值給對象

  • 匿名對象充當(dāng)函數(shù)返回值

如下測試代碼

#include <iostream>
#include <string>
class GirlFriend
{

public:
  GirlFriend(std::string name,int age)
  {
    m_name = name;
    m_age = age;
  }
  void  print() 
  {
    std::cout << m_name << "\t" << m_age << std::endl;
  }
protected:
  std::string m_name;
  int m_age;
};
//用常引用需要調(diào)用常成員函數(shù)
void printObject(GirlFriend&& object) 
{
  object.print();
}
GirlFriend returnObject()
{
  return GirlFriend("匿名對象", 18);
}

int main()
{
  GirlFriend object=GirlFriend("匿名對象",18);
  object.print();
  printObject(GirlFriend("匿名對象", 18));
  returnObject().print();
  return 0;
}

C++析構(gòu)函數(shù)

C++中析構(gòu)函數(shù)是一種特殊的成員函數(shù),用于在對象銷毀時(shí)清理對象所占用的資源。析構(gòu)函數(shù)的名稱與類名相同,前面加上一個(gè)波浪號(~),沒有參數(shù)。

析構(gòu)函數(shù)在以下情況下會(huì)被自動(dòng)調(diào)用:

  • 對象在離開其作用域時(shí),比如一個(gè)局部對象在函數(shù)結(jié)束時(shí);

  • 通過使用 delete 運(yùn)算符進(jìn)行動(dòng)態(tài)分配的內(nèi)存釋放對象;

  • 對象在一個(gè)包含它的程序塊結(jié)束時(shí)。

析構(gòu)函數(shù)可以在銷毀對象時(shí)執(zhí)行必要的內(nèi)存清理操作,如釋放動(dòng)態(tài)分配的內(nèi)存、關(guān)閉文件等資源。如果一個(gè)類擁有指向其他對象的指針、動(dòng)態(tài)分配了內(nèi)存或打開了文件,那么這個(gè)類應(yīng)該定義一個(gè)析構(gòu)函數(shù)來處理這些操作,以避免內(nèi)存泄漏和資源浪費(fèi)的問題。

如下測試代碼

#include <iostream>
#include <string>
class GirlFriend
{

public:
  ~GirlFriend() 
  {
    std::cout << "析構(gòu)函數(shù)" << std::endl;
  }

protected:

};

int main()
{
  {
    //普通對象代碼塊結(jié)束調(diào)用析構(gòu)
    GirlFriend girl;
    //new出來的對象需要delete才會(huì)調(diào)用析構(gòu)
    GirlFriend* p = new GirlFriend;
  }
  std::cout << "--------------" << std::endl;
  {
    //普通對象代碼塊結(jié)束調(diào)用析構(gòu)
    GirlFriend girl;
    //new出來的對象需要delete才會(huì)調(diào)用析構(gòu)
    GirlFriend* p = new GirlFriend;
    delete p;
  }
  return 0;
}

運(yùn)行結(jié)果如下

C++拷貝構(gòu)造函數(shù)

C++的拷貝構(gòu)造函數(shù)(Copy Constructor)是一種特殊的構(gòu)造函數(shù),用于創(chuàng)建一個(gè)新對象并且以傳入的同類對象為初始值。拷貝構(gòu)造函數(shù)在許多場合下自動(dòng)被調(diào)用,例如當(dāng)函數(shù)參數(shù)是一個(gè)對象時(shí)、當(dāng)函數(shù)返回值是一個(gè)對象時(shí)、當(dāng)一個(gè)對象被另一個(gè)對象賦值時(shí),等等。拷貝構(gòu)造函數(shù)唯一的參數(shù)就是對對象的引用,作用就是通過一個(gè)對象產(chǎn)生另一個(gè)對象。

C++拷貝構(gòu)造函數(shù)| 左值引用

左值引用的拷貝構(gòu)造函數(shù),只能實(shí)現(xiàn)左值對象的拷貝,不能傳入常對象,或者右值對象。如下測試代碼:

#include<iostream>
#include<string>
class MM 
{
public:
  MM() {}
  MM(std::string name, int age) 
  {
    m_name = name;
    m_age = age;
  }
  //拷貝構(gòu)造函數(shù)+構(gòu)造函數(shù)委托
  MM(MM& object):MM(object.m_name,object.m_age)
  {

  }
  void print()
  {
    std::cout << m_name << "\t" << m_age << std::endl;
  }

protected:
  std::string m_name;
  int m_age;
};
//不調(diào)用
void printInfo(MM& object) 
{
  object.print();
}
//調(diào)用拷貝構(gòu)造函數(shù)
void printData(MM object) 
{
  object.print();
}
int main()
{
  MM girl("girl", 19);
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM mm = girl;  
  mm.print();
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM baby(mm);
  baby.print();
  //錯(cuò)誤
  //MM error1 = std::move(baby);
  //錯(cuò)誤
  //MM error2(MM("error", 18)) ;
  MM test;
  //不調(diào)用拷貝構(gòu)造函數(shù)
  test = mm;
  printInfo(test);
  printData(test);
  return 0;
}

C++拷貝構(gòu)造函數(shù)| 常引用

常引用的拷貝構(gòu)造函數(shù)要注意的是在拷貝構(gòu)造函數(shù)中不能修改數(shù)據(jù)成員?;旧蠞M足大部分的需求。如下測試代碼:

#include<iostream>
#include<string>
class MM 
{
public:
  MM() {}
  MM(std::string name, int age) 
  {
    m_name = name;
    m_age = age;
  }
  //拷貝構(gòu)造函數(shù)+構(gòu)造函數(shù)委托
  MM( const MM& object):MM(object.m_name,object.m_age)
  {
    //這個(gè)函數(shù)中不能修改object數(shù)據(jù)
  }
  void print()
  {
    std::cout << m_name << "\t" << m_age << std::endl;
  }

protected:
  std::string m_name;
  int m_age;
};
//不調(diào)用
void printInfo(MM& object) 
{
  object.print();
}
//調(diào)用拷貝構(gòu)造函數(shù)
void printData(MM object) 
{
  object.print();
}
int main()
{
  MM girl("girl", 19);
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM mm = girl;  
  mm.print();
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM baby(mm);
  baby.print();
  //正確
  MM ok1 = std::move(baby);
  MM ok2(MM("error", 18));
  MM test;
  //不調(diào)用拷貝構(gòu)造函數(shù)
  test = mm;
  printInfo(test);
  printData(test);
  return 0;
}

C++拷貝構(gòu)造函數(shù)| 右值引用

C++11引入了移動(dòng)語義(Move Semantics)的概念,這種語義的目的是在對象拷貝的過程中避免不必要的復(fù)制操作,從而提高程序的性能。移動(dòng)拷貝(Move Constructor)是一種特殊的構(gòu)造函數(shù),用于將另一個(gè)同類對象的資源所有權(quán)移動(dòng)到一個(gè)新對象中,即移動(dòng)拷貝不是復(fù)制原有對象的數(shù)據(jù),而是基于原對象構(gòu)造一個(gè)新對象,并將原對象的資源指針移到新對象,使新對象掌握該資源的控制權(quán)。相比于常引用來說,在拷貝構(gòu)造函數(shù)中可以修改數(shù)據(jù)。如下測試代碼:

#include<iostream>
#include<string>
class MM 
{
public:
  MM() {}
  MM(std::string name, int age) 
  {
    m_name = name;
    m_age = age;
  }
  //拷貝構(gòu)造函數(shù)+構(gòu)造函數(shù)委托
  MM(MM& object):MM(object.m_name,object.m_age)
  {
  }
  MM(MM&& object) :MM(object.m_name, object.m_age)
  {
    object.m_name = "name";
  }
  void print()
  {
    std::cout << m_name << "\t" << m_age << std::endl;
  }

protected:
  std::string m_name;
  int m_age;
};
//不調(diào)用
void printInfo(MM& object) 
{
  object.print();
}
//調(diào)用拷貝構(gòu)造函數(shù)
void printData(MM object) 
{
  object.print();
}
int main()
{
  MM girl("girl", 19);
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM mm = girl;  
  mm.print();
  //調(diào)用拷貝構(gòu)造函數(shù)
  MM baby(mm);
  baby.print();
  //正確
  MM ok1 = std::move(baby);
  MM ok2(MM("error", 18));

  printInfo(baby);
  printData(baby);
  return 0;
}

C++拷貝構(gòu)造函數(shù)| 深淺拷貝問題

C++類中包含指針的時(shí)候并且做內(nèi)存申請,才會(huì)存在深淺拷貝問題。

  • 淺拷貝:淺拷貝是一種將源對象的指針直接復(fù)制到新對象中的操作。這意味著源對象和新對象共享指向相同位置的內(nèi)存,當(dāng)該對象的生命周期結(jié)束時(shí),會(huì)同時(shí)釋放該內(nèi)存空間。

  • 深拷貝:深拷貝是一種在創(chuàng)建新對象時(shí),將指向源對象的指針重新分配到新的內(nèi)存空間中的操作。這意味著源對象和新對象各自擁有自己的內(nèi)存空間,他們的生命周期互相獨(dú)立。


通常不寫拷貝構(gòu)造函數(shù),會(huì)存在一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),默認(rèn)拷貝構(gòu)造和直接賦值的拷貝構(gòu)造都是淺拷貝,淺拷貝會(huì)引發(fā)內(nèi)存重復(fù)被釋放問題。如下測試代碼:

#include <iostream>
#include <cstring>
using namespace std;
class MM 
{
public:
  MM(const char* str)
  {
    int length = strlen(str) + 1;
    pname = new char[length];
    strcpy_s(pname, length, str);
  }
  MM(MM& object)
  {
    //默認(rèn)拷貝構(gòu)造和直接賦值都是淺拷貝
    pname = object.pname;
  }
  void print() 
  {
    cout << pname << endl;
  }
  ~MM() 
  {
    delete[] pname;
  }
protected:
  char* pname;
};
int main() 
{
  {
    MM mm("淺拷貝");
    MM girl(mm);
    girl.print();
    mm.print();
  }
  return 0;
}

運(yùn)行結(jié)果如下

深拷貝實(shí)現(xiàn)代碼

#include <iostream>
#include <cstring>
using namespace std;
class MM 
{
public:
  MM(const char* str)
  {
    int length = strlen(str) + 1;
    pname = new char[length];
    strcpy_s(pname, length, str);
  }
  //委托構(gòu)造
  MM(MM& object):MM(object.pname)
  {
    //或者自己實(shí)現(xiàn)代碼
    //int length = strlen(object.pname) + 1;
    //pname = new char[length];
    //strcpy_s(pname, length, object.pname);
  }
  void print() 
  {
    cout << pname << endl;
  }
  ~MM() 
  {
    delete[] pname;
  }
protected:
  char* pname;
};
int main() 
{
  {
    MM mm("深拷貝");
    MM girl(mm);
    girl.print();
    mm.print();
  }
  return 0;
}

做了內(nèi)存的在申請,這樣就不會(huì)有問題。

C++構(gòu)造和析構(gòu)順序

C++構(gòu)造和析構(gòu)順序主要有以下三點(diǎn):

  • 普通對象構(gòu)造順序和析構(gòu)順序是相反的

  • new出來的對象,delete時(shí)候立刻馬上調(diào)用析構(gòu)

  • static對象最后被釋放

如下測試代碼:

#include <iostream>
#include <string>
using namespace std;
class MM
{
public:
  MM(string _name="默認(rèn)")
  {
    name = _name;
    cout << name;
  }
  ~MM() 
  {
    cout << name;
  }
protected:
  string name;
};
int main() 
{
  //普通對象,構(gòu)造順序和析構(gòu)順序相反
  cout << "普通對象,構(gòu)造順序和析構(gòu)順序相反" << endl;
  {
    MM a("a");
    MM b("b");
    MM c("c");
  }
  cout <<endl <<"new出來的對象,立刻馬上調(diào)用析構(gòu)" << endl;
  {
    MM a("a");
    MM b("b");
    auto c = new MM("c");
    delete c;
    MM d("d");
    //abccddba
  }
  cout <<endl << "static對象最后被釋放" << endl;
  {
    MM a("a");
    MM b("b");
    static MM s(" static ");
    MM c("c");
  }
  cout << endl << "C++構(gòu)造數(shù)組對象,一般會(huì)準(zhǔn)備無參構(gòu)造函數(shù)" << endl;
  {
    //MM array[3]{ {"a"},{"b"},{"c"}};    //帶參的方式構(gòu)造,比較不推薦 
    //構(gòu)造數(shù)組其實(shí)是三個(gè)無參對象
    MM a("a");
    MM arr[3];
    MM b("b");
  }
  return 0;
}

如果能成功分析程序運(yùn)行結(jié)果,基本就沒什么問題。程序運(yùn)行結(jié)果如下

相關(guān)

如果閣下正好在學(xué)習(xí)C/C++,看文章比較無聊,不妨關(guān)注下關(guān)注下小編的視頻教程,通俗易懂,深入淺出,一個(gè)視頻只講一個(gè)知識點(diǎn)。視頻不深?yuàn)W,不需要鉆研,在公交、在地鐵、在廁所都可以觀看,隨時(shí)隨地漲姿勢。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美日韩综合在线第一页 | 99久免费精品视频在线观| 绝望的校花花间淫事2| 国产一区二区三区四区中文| 久久天堂夜夜一本婷婷| 免费特黄一级一区二区三区| 好东西一起分享老鸭窝| 亚洲欧洲一区二区综合精品| 亚洲熟妇av一区二区三区色堂| 午夜视频成人在线观看| 日本一二三区不卡免费| 麻豆剧果冻传媒一二三区| 欧美成人黄色一区二区三区| 欧美成人免费视频午夜色| 欧美又黑又粗大又硬又爽| 91亚洲精品国产一区| 青青久久亚洲婷婷中文网| 欧美黄色黑人一区二区| 亚洲性生活一区二区三区| 黑丝国产精品一区二区| 亚洲国产丝袜一区二区三区四| 尹人大香蕉中文在线播放| 国产精品日本女优在线观看| 精品女同一区二区三区| 亚洲欧洲精品一区二区三区| 在线观看欧美视频一区| 国产成人av在线免播放观看av| 亚洲精品国产美女久久久99| 久久99夜色精品噜噜亚洲av| 国产又粗又爽又猛又黄的 | 亚洲一区二区三区熟女少妇| 成年午夜在线免费视频| 午夜国产精品国自产拍av| 高清一区二区三区四区五区| 亚洲精品中文字幕熟女| 高清不卡视频在线观看| 亚洲日本加勒比在线播放| 国产av大片一区二区三区| 极品少妇嫩草视频在线观看| 国产精品尹人香蕉综合网| 日本乱论一区二区三区|