在學習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...