下屬專案
測試用例數量
方式三:在函式中把類作為形參無1
方式四:在函式中把類作為返回值型別+陷阱無1
#define _crt_secure_no_warnings
#include
"iostream"
using
namespace std;
#include
class
test
void
seta
(int a)
intgeta()
char
*getbuf()
void
print()
private
:int m_a;
char buf[32]
;};test::
test()
test::
~test()
test::
test
(test &obj)
void
fun4
(test p)
//形參型別是類,實參傳給形參,執行的是拷貝構造
void
objplay2()
void
main()
這一段**和上篇部落格的相比,僅僅是新增了乙個fun4()的函式,其形式引數是乙個類,在**中我把這種拷貝構造呼叫注釋為了方式三。在實際的測試中,可以去掉方式一和二,單獨觀察方式三的行為,就會知道在把實參傳給形參的時候,執行的不是通常的賦值而是執行拷貝建構函式來傳值的。1
#define _crt_secure_no_warnings
#include
"iostream"
using
namespace std;
#include
class
position
public
:int
geta()
char
*getbuf()
private
:int m_a;
char buf[32]
;};position::
position()
position::
position
(int a,
char
*strsrc)
position::
position
(position &obj)
position::
~position()
position fun()
void
objplay4()
void
main()
在這段**中,我注釋掉了正確的呼叫方式。也就是說,你拷貝執行這段**絕對會出錯。
重點在於對那個匿名的中間物件的理解。
在fun()的注釋中我也說得很清楚,如果乙個函式的返回值型別是類的話,返回的時候就會拷貝構造乙個匿名的中間物件,如果返回後是賦給乙個引用或者說是用於乙個類的型別的變數的初始化,那麼中間物件將直接成為那個物件,其生命週期將會持續。
對於引用而言其實也是初始化,因為引用要求在定義的時候就必須初始化,也就是說返回後同樣是用於類的初始化,其生命週期將持續。
就結論而言,非常簡單:如果返回後有乙個物件(未初始化)去接這個中間物件,中間物件將直接成為那個物件,其生命週期持續;如果返回後僅僅是乙個簡單的=操作,那麼這個中間物件將會析構,其生命週期結束。
至於這裡隱藏的陷阱,也就是記憶體的問題了,因為=執行的是淺拷貝,那麼b變數裡面的指標改變了記憶體空間的指向,那麼原來的記憶體就會洩露(沒有釋放掉),而且由於新的淺拷貝過來的指標指向的是那個匿名中間物件的記憶體空間,但中間物件因為沒有未初始化的物件去接已經析構了,那麼從函式objplay4()返回的時候就會出錯,畢竟同一片記憶體是不能釋放兩次的。1
如果本文對你有幫助,不如請我一罐可樂吧 ?
方式三:在函式中把類作為形參
方式四:在函式中把類作為返回值型別+陷阱
測試用例基於王保明先生的講課內容. ↩︎↩︎
拷貝建構函式的兩種呼叫方式
下屬專案 測試用例數量 什麼是拷貝建構函式無1 兩種呼叫方式是什麼無1 define crt secure no warnings include iostream using namespace std include class test void seta int a intgeta char...
拷貝構造函式呼叫的時機
拷貝函式何時會被呼叫呢?最明顯的就是用乙個類物件初始化另外乙個物件的時候 比如x a x 這句語義上就是先建立x 臨時物件,再呼叫x的拷貝建構函式 初始化 a,這只是語義上的,編譯器完全可能優化掉臨時物件 注意區分初始化和賦值 呼叫assignment operator 第二種情況是函式按值傳引數的...
C 拷貝建構函式的呼叫
晚上做c 作業,碰到乙個拷貝函式的問題,看了會書也沒太看明白,回到寢室馬上試驗了下才差不多弄清楚了拷貝建構函式及臨時物件的呼叫。拷貝建構函式主要在以下三種情況下起初始化作用 1.在宣告語句中用乙個物件初始化另乙個物件 2.將乙個物件作為引數按值呼叫方式傳遞給另乙個物件時生成物件副本 3.生成乙個臨時...