📄 returnby.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="css/stdlayout.css" type="text/css">
<link rel="stylesheet" href="css/print.css" type="text/css">
<meta content="text/html; charset=gb2312" http-equiv="content-type">
<title>return 的传值、传参考</title>
</head>
<body>
<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>
<h1><a href="CppGossip.html">C++
Gossip: <span class="Topic">return 的传值、传参考</span><br>
</a></h1>
<br>
在定义函式时,一定要定义函式的传回值型态,如果函式不传回值,则使用void表示不传回任何数值;一旦指定函式的传回值不为void,则在函式中一定要
使用return传回一个数值,否则编译器将回报错误。 <br>
<br>
在之前的范例中,您只是使用传值的方式传回函式的执行结果,事实上您也可以传回一个指标或是参考,传回指标通常意味着您要对这个指标所指向的记忆体位置作
取值或更动的动作,例如下面的程式中,您在函式中动态建立一个阵列,并传回它的指标值: <br>
<br>
<pre>#include <iostream> <br>using namespace std; <br><br>int* createArray(int);<br>void deleteArray(int*);<br><br>int main() { <br> int m = 0; <br><br> cout << "阵列大小: "; <br> cin >> m; <br><br> int *arr = createArray(m); <br><br> for(int i = 0; i < m; i++) {<br> arr[i] = i; <br> }<br> <br> for(int i = 0; i < m; i++) {<br> cout << "arr[" << i << "] = " <br> << arr[i] << endl; <br> }<br><br> deleteArray(arr);<br><br> return 0; <br>} <br><br>// 传回建立的阵列位址<br>int* createArray(int m) { <br> int *a = new int[m]; <br><br> for(int i = 0; i < m; i++) {<br> a[i] = 0; <br> }<br><br> return a; <br>}<br><br>void deleteArray(int* arr) {<br> delete [] arr; <br>}</pre>
<span class="postbody"><br>
执行结果:</span><br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">阵列大小: 5<br>
arr[0] = 0<br>
arr[1] = 1<br>
arr[2] = 2<br>
arr[3] = 3<br>
arr[4] = 4</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
由于您使用动态配置的方式,所以在使用delete之前,这块被配置的记忆体并不会自动清除,所以您可以直接传回给呼叫函式的主函式,注意如果您不是使用
new来配置,则在副函式中所宣告的变数记忆体,在函式执行结束后都会自动消失,则您传回指标值也就没有意义,也会造成存取错误,因为该块记忆体在副函式
执行完毕后已经自动回收了。 <br>
<br>
在这边的范例您也看到了如何传递阵列给函式,以及如何传回一个阵列,在C++中传递阵列或传回阵列一律使用传址方法,因为阵列名称本身就是个指标,储存有
位址资讯。<br>
<br>
在进一步讨论传参考之前,您先要了解到,在C++中传递一个物件,预设也是使用传值的方式,例如下面这个程式: <br>
<br>
<pre>#include <iostream> <br>#include <string> <br>using namespace std; <br><br>string foo(); <br><br>int main() { <br> string str; // 空字串<br><br> str = foo(); <br><br> cout << "address: " << &str <br> << endl << str << endl; <br> <br> return 0; <br>} <br><br>string foo() { <br> string s = "This is caterpillar speaking."; <br><br> cout << "address: " << &s <br> << endl << s << endl; <br><br> return s; <br>}<br></pre>
<span class="postbody"><br>
执行结果:</span><br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">address: 0x22ff40<br>
This is caterpillar speaking.<br>
address: 0x22ff50<br>
This is caterpillar speaking.</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
您可以发现到,两个字串的记忆体位置并不相同,表示传回的字串在传值时是复制一份新的传回,您可以改用传参考的方式将字串值传回,方式如下所示: <br>
<br>
<pre>#include <iostream> <br>#include <string> <br>using namespace std; <br><br>string& foo(); <br><br>int main() { <br> string &str = foo(); <br><br> cout << "address: " << &str <br> << endl << str << endl; <br><br> delete &str; <br><br> return 0; <br>} <br><br>string& foo() { <br> string *s = new string("This is caterpillar speaking."); <br><br> cout << "address: " << s <br> << endl << *s << endl; <br><br> return *s; <br>}<br></pre>
<span class="postbody"><br>
</span><span class="postbody">执行结果:</span><br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">address: 0x3d2458<br>
This is caterpillar speaking.<br>
address: 0x3d2458<br>
This is caterpillar speaking.</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
使用传参考的方式是直接告知物件的记忆体位置,而没有作物件复制的动作,可以加快程式执行的效率,而某些情况下,编译器也会自行将物件的传回结果自动设定
为传参考,即使语法上并没有指定,例如: <br>
<br>
<pre>#include <iostream> <br>#include <string> <br>using namespace std; <br><br>string foo(); <br><br>int main() { <br> string str = foo(); // 空字串<br><br> cout << "address: " << &str <br> << endl << str << endl; <br> <br> str = foo(); // 指定新字串,会复制一份<br> <br> cout << "address: " << &str <br> << endl << str << endl; <br> <br> return 0; <br>} <br><br>string foo() { <br> string s = "This is caterpillar speaking."; <br><br> cout << "address: " << &s <br> << endl << s << endl; <br><br> return s; <br>}<br></pre>
<span class="postbody"><br>
</span><span class="postbody">
执行结果:</span><br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">address: 0x22ff50<br>
This is caterpillar speaking.<br>
address: 0x22ff50<br>
This is caterpillar speaking.<br>
address: 0x22ff40<br>
This is caterpillar speaking.<br>
address: 0x22ff50<br>
This is caterpillar speaking.</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
在这个程式中,第一行宣告str并指定foo()传回值时,虽然并没有指定传回参考,但是您可以看到两个字串变数的值都指向同一块记忆体,但是编译器会自
动判断并以传参考的方式来传回这个物件,而不是使用传值的方法传回,这是编译器的功能,您可以将之当作一个效率上的考量作法,但不可以将之当作一个传参考
的方式来使用。 <br>
<br>
必须注意的是,函式中的区域变数在函式开始时被配置,在函式结束后所占有的记忆体位址也会被清除,绝对不要传回一个区域变数的位址给呼叫者,或是以传参考
的方式传回一个区域变数,因为您所存取的记忆体位址中资料是未知的,所以结果是不可预期的。<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -