C 方法返回值為引用時會發生什麼

2021-10-01 02:34:59 字數 2818 閱讀 9248

在學習qt的過程中,看到有些內建的qt庫中存在一些返回引用的方法,例如:

等等,所以有點好奇,返回值與返回引用之間有什麼區別呢?遂有了這篇文章。

在寫驗證程式的時候又對c++的建構函式、拷貝建構函式、賦值建構函式有了新的理解,文章末會放出完整的測試**。

第一步,我們需要乙個類,給他起個名字,就叫a吧。
classaa

(const a &y)~a

()void

run(

)public

:int mi;

};

這個a類,我們重寫了它的建構函式、拷貝建構函式、析構函式以便使我們可以觀測到程式的執行步驟。

第二步,我們還需要幾個返回a的方法:

static a newa

(a &a)

;static a newa2

(a &a)

;static a &

newa3

(a &a)

第三步,開始測試
int

main

(int argc,

char

*ar**)

return a.

exec()

;}

上面程式的執行結果為:

0x65fe9c a 物件通過建構函式建立 33

0x65fe98 a 物件通過建構函式建立 1

0x65fe98 run() 1

a4.run();

0x65fe98 ~a() 1

0x65fe9c ~a() 33

aaa通過引用傳遞的方式傳入newa方法,這個過程不會發生拷貝構造,然後newa方法內,a aa(1);語句通過建構函式建立了乙個物件aa,然後它作為返回值返回,並且aa物件的生存週期延長至程式結束。

0x65fe9c a 物件通過建構函式建立 33

0x65fe6c a 物件通過建構函式建立 2

0x65fe98 a 物件通過拷貝建構函式建立 6684520 被拷貝的物件是: 0x65fe9c

0x65fe6c ~a() 2

0x65fe98 run() 6684520

a4.run();

0x65fe98 ~a() 6684520

0x65fe9c ~a() 33

newa2方法與newa方法唯一的不同便是返回的值不同,newa2方法返回的不是在newa2方法內建立的區域性變數,而是傳入的實參。

因此程式執行的結果在這發生了不同,在newa2方法的最後,呼叫拷貝建構函式構造了乙個新的物件,這個新的物件作為返回值返回。

我們可以看到執行run()方法時,mi值變為了6684520而不是33,這是因為我們過載了拷貝建構函式,並且啥也不幹,如果我們不過載拷貝建構函式的話,mi的值會是33。不信你試試/滑稽。我不知道這是為啥,改天再研究下。

0x65fe9c a 物件通過建構函式建立 33

0x65fe6c a 物件通過建構函式建立 3

0x65fe6c ~a() 3

0x65fe98 a 物件通過拷貝建構函式建立 6684520 被拷貝的物件是: 0x0

0x65fe98 run() 6684520

a4.run();

0x65fe98 ~a() 6684520

0x65fe9c ~a() 33

這段輸出乍看上去跟上面那個很相似,但是。。。。。

輸出的不同點在於輸出的第

三、四行。呼叫newa3方法,是先析構區域性變數aa,然後再拷貝構造實參aa。這個順序就有問題了啊。已經被析構的區域性變數,如何才能作為拷貝構造方法的引數呢?雖然程式正常執行了,但是存在訪問非法記憶體的風險。

下面放出完整的測試**

#include

#include

#include

class

a//拷貝構造,一般在傳參時使用,或者是返回非引用(僅限返回值為引用傳參),或者是a(

const a &y)~a

()void

run(

)//賦值建構函式

a &operator=(

const a &other)

public

:int mi;};

//若是實參以值傳遞方式傳入,那麼會呼叫拷貝建構函式構造a。

static a newa

(a &a)

;//以值傳遞方式返回,那麼會呼叫拷貝建構函式構造乙個返回值。

//若是實參以值傳遞方式傳入,那麼還會呼叫拷貝建構函式構造a,a的析構發生在上行拷貝構造之後。

static a newa2

(a &a)

;//返回引用時,會呼叫拷貝建構函式構造出乙個返回值,不同於newa2,拷貝構造發生在

// a aa(3)物件析構之後。!!!!!!該問題導致,被拷貝的物件已經被析構,導致程式會出現漏洞。

//實參為值傳遞時,仍會呼叫拷貝建構函式,但是該物件在拷貝構造之後才會析構

static a &

newa3

(a &a)

//實參為值傳遞時,輸出變得很奇怪

static a &

newa4

(a &a)

intmain

(int argc,

char

*ar**)

return a.

exec()

;}

c 返回值為引用

與返回原值的區別 return的位址和返回值的位址是同乙個,也就是佔據著同一塊記憶體,因此要求此時return的東西必須是乙個實體 有儲存位址 不能是乙個作用域僅在函式中的區域性變數 例如 int fun a fun 就會報錯。因為a找不到它應該存在的位址在 int fun int c a fun ...

c c 返回值為指標 引用時注意的地方

全域性變數,區域性靜態變數,區域性動態分配變數 都可以作為函式返回值。但是,區域性自動變數不能作為函式返回值。可以看出來,函式內部等區域性變數,儲存在棧中的變數是不能作為返回值的,雖然可以讀取正確的值,但是這是一塊未分配的記憶體,當別的程序用到時就會出錯,這個指標相當於野指標。返回值可以是區域性動態...

c 引用返回值

函式返回值時,要生成乙個值的副本。而用引用返回值時,不生成值的副本。例如,下面的程式是有關引用返回的4種形式 ch9 6.cpp include float temp float fn1 float r float fn2 float r void main void main 見圖9 9說明。圖9...