函數(shù)返回指針。本來(lái)就是一個(gè)比較容易出問(wèn)題的操作。在霍頓的《VC++ 入門(mén)經(jīng)典》一書(shū)中,給出了一個(gè)很有代表性的例子,如下:
// Ex5_11.cpp
#include <iostream>
using std::cout;
using std::endl;
double* treble(double); // Function prototype
int main(void)
{
double num = 5.0; // Test value
double* ptr = 0; // Pointer to returned value
ptr = treble(num);
cout << endl
<< "Three times num = " << 3.0*num;
cout << endl
<< "Result = " << *ptr; // Display 3*num
cout << endl;
system("pause");
return 0;
}
// Function to treble a value - mark 1
double* treble(double data)
{
double result = 0.0;
result = 3.0*data;
return &result;
}
兩個(gè)輸出語(yǔ)句,一個(gè)直接輸出3*5=15.另一個(gè)在一個(gè)函數(shù)中進(jìn)行了乘法運(yùn)算,也是5*3, 存到result變量中也沒(méi)有任何問(wèn)題。返回這個(gè)變量的指針,輸出時(shí)再接觸引用。貌似也沒(méi)有錯(cuò)誤。兩條輸出語(yǔ)句似乎都應(yīng)該輸出15.但事實(shí)不是這樣。編譯 器會(huì)拋出[Warning] address of local variable `result' returned 這樣一個(gè)警告信息。程序運(yùn)行后的結(jié)果也并非是我們預(yù)想的那樣。第二條輸出語(yǔ)句會(huì)輸出一個(gè)不可預(yù)見(jiàn)的值。這是怎么回事呢?
仔細(xì)分析一下,result是作用域在treble函數(shù)中的局部變量。當(dāng)函數(shù)執(zhí)行結(jié)束后。變量result會(huì)被析構(gòu)。其原先占用的內(nèi)存區(qū)域已經(jīng)被系統(tǒng)回收,可以存儲(chǔ)任何數(shù)據(jù)。而返回的指向該地址的指針也失去了其原有的意義。因此我們得到這樣一條準(zhǔn)則:
永遠(yuǎn)不要從函數(shù)中返回局部自動(dòng)變量的地址。
如果你真的需要這樣操作。你可以在函數(shù)的參數(shù)表中傳入一個(gè)指針變量。然后將需要寫(xiě)入的數(shù)據(jù)寫(xiě)入到該指針變量指向的地址。由于該指針指向的變量,作用域在函數(shù)體 之外。因此不會(huì)在函數(shù)結(jié)束結(jié)束時(shí)被回收。
現(xiàn)在回到我們遇到的問(wèn)題。時(shí)間函數(shù)localtime就是一個(gè)返回指針的函數(shù)。返回值類(lèi) 型:tm*
該如何接收這個(gè)返回值?當(dāng)然是聲明一個(gè)與之類(lèi)型相同的變量。
于是你會(huì)這樣寫(xiě):tm* result;
接下來(lái)呢?還用問(wèn)?賦值嘛。是不是這樣:result=localtime(....);
返回什么類(lèi)型,當(dāng)然要給什么類(lèi)型的變量 賦值。但是這樣卻發(fā)生了我們不想看到的結(jié)果。
也許你想到了。就是這個(gè)指針!返回的指針在函數(shù)結(jié)束后不再有效。正確的方法可以是:
tm result;
result = *localtime(....);
也可以是:
tm* result;
*result = *localtime(...);
正確的方法的共同特點(diǎn)是在函數(shù)結(jié)束前,對(duì)返回的指針解除引用。然后用這個(gè)數(shù)值,為變量或指針指向的內(nèi)存區(qū)域賦值。也就是說(shuō)必須要復(fù)制函 數(shù)的返回值。因?yàn)楹瘮?shù)體中變量會(huì)被析構(gòu)。
指針是靈活而強(qiáng)大的,避免低級(jí)錯(cuò)誤,明確基本概念。才能讓指針更好的為我們服務(wù)。
新聞熱點(diǎn)
疑難解答