拷貝構造函數

拷貝構造函數是一種特殊的構造函數,它在創建對象時,使用的是同一類中之前創建的對象來初始化新創建的對象。拷貝構造函數通常用于:

l? 通過使用另一個同類型的對象來初始化新創建的對象;

l? 復制對象把它作為參數傳遞給函數;

l? 復制對象,并從函數返回這個對象。

?

如果類中沒有定義拷貝構造函數,編譯器會自行定義一個。如果類中帶有指針變量,并有動態內存分配,則它必須有一個拷貝構造函數。拷貝構造函數最常見的形式如下:

classname(const classname &obj)
{//構造函數主體
}

在這里,obj是一個對象的引用,該對象是用于初始化另一個對象的。

/***
copy_constructor.cpp
***/
#include<iostream>
using namespace std;class Line
{public:Line(int len);Line(const Line & obj);~Line();    int getLength(void);private:int *ptr;
};Line::Line(int len)
{cout << "call construct func" << endl;//allocate memory for pointer    ptr = new int;*ptr = len;
}Line::Line(const Line &obj)
{cout << "call copy constructor func and allocate memory for point" << endl;ptr = new int;*ptr = *obj.ptr;
}Line::~Line(void)
{cout << "free memory" << endl;delete ptr;
}int Line::getLength(void)
{return *ptr;
}void display(Line obj)
{cout << "the size of line : " << obj.getLength() << endl;
}int main()
{Line line(10);display(line);return 0;
}

運行結果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

call construct func

call copy constructor func and allocate memory for point

the size of line : 10

free memory

free memory

?

void display(Line obj) //通過gdb調試,該程序在 Line obj處進入拷貝函數構造。

?

如果使用以下的main

int main()
{Line line1(10);Line line2 = line1;display(line1);display(line2);return 0;
}

運行結果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

call construct func

call copy constructor func and allocate memory for point

call copy constructor func and allocate memory for point

the size of line : 10

free memory

call copy constructor func and allocate memory for point

the size of line : 10

free memory

free memory

free memory

?

在C++中,對象以值傳遞的方式傳入函數參數:

/***
value_transf.cpp
***/
#include<iostream>
using namespace std;class CExample
{public:CExample(int b){a = b;cout << "create: " << a << endl;}//copy constructorCExample(const CExample& C){a = C.a;cout << "copy constructor" << endl;}//destructor~CExample(){cout << "delete: " << a << endl;}void show(){cout << a << endl;}private:int a;
};void g_Fun(CExample C)
{cout << "test" << endl;
}int main()
{CExample test(1);g_Fun(test);return 0;
}

運行結果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ g++ value_transf.cpp -o value_transf -g

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./value_transf

create: 1

copy constructor

test

delete: 1

delete: 1

調用g_Fun()時,會產生以下幾個重要的步驟:

1) test對象傳入形參時,會先產生一個臨時變量,暫且稱呼C

2) 然后調用拷貝構造函數把test值給C。這兩個步驟很像:CExample C

3) 等g_Fun()執行完后,析構掉C對象。

?

拷貝構造函數是一種特殊的構造函數,具有單個形參,該形參(常用const修飾)是對該類類型的引用。當定義一個新對象并用一個同類型的對象把它進行初始化時,將顯示使用拷貝構造函數或從函數返回該類型的對象時,將隱式調用拷貝構造函數。

?

C++支持兩種初始化形式:

拷貝初始化:int a = 5;和直接初始化 int a(5);

對于其他類型沒有什么區別,對于類類型直接初始化直接調用實參匹配的構造函數,拷貝構造初始化總是調用拷貝構造函數,也就是說

A x(2);? //直接初始化,調用構造函數

A y = x; //拷貝初始化,調用拷貝構造函數。

必須定義拷貝構造函數的情況:

只包含類類型成員或內置類型(但不是指針類型)成員的類,無須顯示地定義拷貝構造函數也可以拷貝;有的類有一個數據成員是指針,或者是由成員表示在構造函數中分配的其他資源,這兩種情況下都必須定義拷貝構造函數。

?

以下情況使用拷貝構造函數:

類的對象需要拷貝時,拷貝構造函數將會調用。以下情況都會調用拷貝構造函數:

l? 一個對象以值傳遞的方式進入函數體

l? 一個對象以值傳遞的方式從函數返回

l? 一個對象需要通過另外一個對象進行初始化

?

轉載于:https://www.cnblogs.com/wanghao-boke/p/11310843.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384901.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384901.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384901.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux進程通信之管道

進程間完成數據傳遞需要借助操作系統提供的特殊的方法&#xff0c;比如&#xff1a;文件、管道、信號、共享內存、消息隊列、套接字、命名管道等。但現在常用的進程間通信方式有&#xff1a; 管道 – 使用最簡單 pipe 管道一般讀寫行為 FIFO&#xff08;有名管道&#xff09;&a…

Linux進程通信之文件

父子進程共享打開的文件描述符------使用文件完成進程間通信. /*** fork_share_fd.c***/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/wait.h>int main(void) {in…

dup2函數

將當前系統中的進程信息打印到文件中 命令行&#xff1a;ps aux > out 將ps得到的信息重定向到out文件中 使用dup2文件在程序中完成。 int dup2(int oldfd,int newfd); /*** dup2.c ***/ #include<stdio.h> #include<fcntl.h> #include<unistd.h> #includ…

wait()函數

wait()函數&#xff1a;回收僵尸進程 父進程調用wait函數可以回收子進程終止信息。該函數有三個功能&#xff1a; 1&#xff09; 阻塞等待子進程退出 2&#xff09; 回收子進程殘留資源 3&#xff09; 獲取子進程結束狀態&#xff08;退出原因&#xff09; /*** zoom_test.c **…

waitpid()函數

waitpid函數 作用同于wait&#xff0c;但可指定pid進程清理&#xff0c;可以不阻塞。 pid_t waitpid(pid_t pid,int *status,int options);成功&#xff1a;返回清理掉的子進程ID&#xff1b;失敗&#xff1a;-1&#xff08;無子進程&#xff09; 特殊參數和返回情況&#xff1…

孤兒進程、僵尸進程

孤兒進程&#xff1a;父進程先于子進程結束&#xff0c;則子進程成為孤兒進程&#xff0c;子進程的父進程成為init進程&#xff0c;稱為init進程領養孤兒進程。 /*** orphan.c ***/ #include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main(v…

友元函數

類的友元函數是定義在類外部&#xff0c;但有權訪問類的所有私有成員和保護成員。盡管友元函數的原型有在類的定義中出現過&#xff0c;但友元函數并不是成員函數。 友元可以是一個函數&#xff0c;該函數被稱為友元函數&#xff1b;友元也可以是一個類&#xff0c;該類被稱為友…

this指針

在C中&#xff0c;每一個對象都能夠通過this指針來訪問自己的地址。this指針是所有成員函數的隱含參數。因此&#xff0c;在成員函數內部&#xff0c;它可以用來指向調用對象。 友元函數是沒有this指針的&#xff0c;因為友元不是類的成員&#xff0c;只有成員函數才有this指針…

靜態成員

我們可以使用static關鍵字把類成員定義為靜態的。當我們聲明類的成員為靜態時&#xff0c;這意味著無論創建多少個類的對象&#xff0c;靜態成員都只有一個副本。 靜態成員在類的所有對象都是貢獻的。如果不存在其他的初始化語句&#xff0c;在創建第一個對象時&#xff0c;所有…

Linux進程通信之mmap

mmap()函數&#xff1a; void *mmap(void* addr,size_t length,int port,int flags,int fd,off_t offset); 返回&#xff1a;成功&#xff1a;返回創建的映射區首地址&#xff1b;失敗&#xff1a;MAP_FAILED 宏 參數&#xff1a; addr: 建立映射區的首地址&#xff0c;由…

Linux之文件通信

/** 后執行,嘗試讀取另外一個進程寫入文件的內容*/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h>int main(void) {char buf[1024];char *str "----------test2 write secesuss---…

重載函數和重載運算符

C允許在同一個作用域中的某個函數和運算符指定多個定義&#xff0c;分別稱為函數重載和運算符重載。 重載聲明是指一個與之前已經在該作用域內聲明過的函數或方法具有相同名稱的聲明&#xff0c;但他們的參數列表和定義&#xff08;實現&#xff09;不相同。 當調用一個重載函數…

二元運算符重載

以非成員函數方式重載運算符 /*** overtwo.cpp ***/ #include<iostream> using namespace std;class Box {public:Box(double l 2.0,double b 2.0,double h 2.0){length l;breadth b;height h;}double getVolume(){return length*breadth*height;}private:double l…

一元運算符重載

一元運算符只對一個操作數進行操作&#xff0c;下面是一元運算符實例&#xff1a; 遞增運算符&#xff08;&#xff09; 和遞減運算符&#xff08;--&#xff09;一元減運算符&#xff0c;即符號&#xff08;-&#xff09;邏輯非運算符&#xff08;!&#xff09;/*** overone.c…

關系運算符重載

C語言支持各種關系運算符重載(<,>,>,<,)&#xff0c;他們可用于比較C內置的數據類型。 支持重載任意一個關系運算符&#xff0c;重載后的關系運算符可以用于比較類的對象。 /*** overrealate.cpp ***/ #include<iostream> using namespace std;class Distanc…

kill函數

kill函數/命令產生信號 kill命令產生信號&#xff1a;kill -SIGKILL pid kill函數&#xff1a;給指定進程發送指定信號(不一定殺死) int kill(pid_t pid, int sig); 成功&#xff1a;0&#xff1b;失敗&#xff1a;-1 (ID非法&#xff0c;信號非法&#xff0c;普通用戶殺i…

下標運算符重載

重載該運算符用于增強操作C數組的功能。 /*** subscript.cpp ***/ #include<iostream> using namespace std; const int SIZE 10;class safearay {private:int arr[SIZE];public:safearay(){register int i;for(i 0; i < SIZE ;i){arr[i] i;} }int& operator…

賦值運算符重載

重載賦值運算符&#xff08;&#xff09;&#xff0c;用于創建一個對象&#xff0c;比如拷貝構造函數。 /*** evaluate.cpp ***/ #include<iostream> using namespace std;class Distance {private:int feet;int inches;public:Distance(){feet 0;inches 0;}Distance(i…

運算符小括號重載

函數調用運算符()可以被重用于類的對象。當重載()時&#xff0c;沒有創造一個新的調用函數的方式&#xff0c;相反地&#xff0c;這是創建一個可以傳遞任意數目參數的運算符函數。 /*** bracke.cpp ***/ #include<iostream> using namespace std;class Distance {private…

自增自減運算符重載

遞增運算符&#xff08;&#xff09;和遞減運算符&#xff08;--&#xff09;是C語言中兩個重要的一元運算符。 /*** addMyself.cpp ***/ #include<iostream> using namespace std;class Time {private:int hours;int minutes;public:Time(){hours 0;minutes 0;}Time(i…