這個部分只要就是說例項了,我看的書是c++ primerplus,第十二章裡面開始的時候就有好大的篇幅講解複製建構函式以及賦值操作符。
使用引用的時機。流操作符《和》、賦值操作符=的返回值、拷貝建構函式的引數、賦值操作符=的引數、其它情況都推薦使用引用。
這個程式裡面到處都是&,也就是引用,引用當然可以不用了,我會一一改變程式來說明這一點,但是使用引用就可以帶來很多方便,或者說可以解決很多意想不到的問題。
程式最初給出的含錯程式就是這樣的,很長了:
標頭檔案strngbad.h:
// strngbad.h -- flawed string class definition
#include
#ifndef strngbad_h_
#define strngbad_h_
class stringbad
;#endif
原始檔strngbad.cpp :
// strngbad.cpp -- stringbad class methods
#include // string.h for some
#include "strngbad.h"
using std::cout;
// initializing static class member
int stringbad::num_strings = 0;
// class methods
// construct stringbad from c string
stringbad::stringbad(const char * s)
stringbad::stringbad() // default constructor
stringbad::~stringbad() // necessary destructor
std::ostream & operator<<(std::ostream & os, const stringbad & st)
包含main 的原始檔vegnews.cpp:
// vegnews.cpp -- using new and delete with classes
// compile with strngbad.cpp
#include
using std::cout;
#include "strngbad.h"
void callme1(stringbad &); // pass by reference
void callme2(stringbad); // pass by value
int main()
void callme1(stringbad & rsb)
void callme2(stringbad sb)
void callme1(stringbad & rsb)
這個函式在呼叫的時候不會再呼叫別的函式,因為他在呼叫的時候,進行的是位址的傳遞,main中的呼叫語句是:callme1(headline1);其實就是把headline1的位址傳遞給rsb這個變數,使用的是引用,這樣就使得,兩者的位址和值都是一樣的,就是c/c++中的很簡單的乙個引用級別的位址傳遞,不呼叫其他函式。
再看函式裡面的cout這個東西,這個東西在其他的地方也看到過,但是這個地方跟其他的地方的變數有點區別的,他在這裡是用的是類stringbad裡面的乙個友員函式,而不是簡單的標準的io流,具體的看stringbad裡面的定義。
下面的這個呼叫就有點問題了,這個就有乙個傳值和賦值的問題了。如果是乙個簡單的內建變數型別的傳值和賦值就是可以直接的進行也不要呼叫其他的函式,或者說即使呼叫也不會出現我們無法控制的問題,這裡就不同了,他會再呼叫乙個隱式複製函式,如果作者沒有給定顯式複製函式的話
void callme2(stringbad sb); // pass by value
這個函式在程式裡面使用過一次,問題在這裡就開始產生headline2傳遞給sb之後進行賦值,就是stringbad sb=headline2,注意了,stringbad sb=headline2和stringbad sb;sb =headline2;這樣的寫法是不一樣的,後面講。
上面已經說過了,如果沒有顯式的複製函式就會自動呼叫或者說系統會幫你構造乙個隱式複製函式,呵呵系統對我們真的好,有的時候這個好就出了問題了,這個好也就是程式的執行結果裡面為什麼會出現亂碼,以及出現析構時的-1,-2的緣故。
看看建構函式:
// construct stringbad from c string
stringbad::stringbad(const char * s)
stringbad::stringbad() // default constructor
每次構造乙個類物件的時候就會把num_strings++執行,增加計數。
在新建乙個物件並將其用另乙個同類類物件初始化的時候都會呼叫複製建構函式stringbad::stringbad(const stringbad &st),就是看時隱式還是顯式的了。
隱式的沒有顯示的那麼符合人的意思了,他就是複製而且給值,我們要求num_strings++但是他能做的就是最基本的給值,不會幫我們++這麼一下。這個時乙個方面,另乙個方面才是最恐怖的,就是系統自己給我們的隱式複製函式是臨時的!臨時的是什麼意思?就是說,當乙個變數活到頭了就要消失了:
stringbad sb=headline2
這個語句會執行,把headline2的成員的量都給sb以後,就要執行析構函式,把sb給析構了,但是headline和sb的str字串指標都是指向的乙個位置,那麼當把sb給析構的同時,headline也被析構了,再要用std::ostream & operator<<(std::ostream & os, const stringbad & st)這個函式來顯示str量就不對了,因為要對乙個已經不存在的位址進行讀或者寫都是會導致異常的。這個就是後來的亂碼的來由!
怎麼辦?
給出顯示的複製建構函式:可以用指標的也可以用引用的:
由於stringbad sb=headline2相當於:stringbad sb=stringbad::stringbad(headline2),那麼這麼構造:
stringbad::stringbad(const stringbad &st)
這個是引用的,指標的就後來再看。
錯誤已經解決的差不多了,下面還有乙個問題, stringbad knot; knot = headline1;這兩條語句就跟上面的stringbad sb=headline2不一樣了,起碼過程不一樣,分為兩步,第一步就是初始化knot,這個由預設建構函式執行,第二步就是knot = headline1賦值,這個也沒有給出函式原型,系統又來幫忙了,幫我們構造隱式的一些建構函式,這個也是我們看不見的,所以我們要自己來給出乙個成員函式或者友員函式。
成員函式:
stringbad & stringbad::operator=(const stringbad &st)
也是用了引用的形式,使用的是過載賦值符號。到這裡差不多可以給出完整的正確的程式了:
原始檔strngbad.cpp :
// strngbad.cpp -- stringbad class methods
#include // string.h for some
#include "stringbad.h"
//using std::cout;
using namespace std;
// initializing static class member
int stringbad::num_strings = 0;
// class methods
// construct stringbad from c string
stringbad::stringbad(const char * s)
stringbad::stringbad() // default constructor
stringbad::~stringbad() // necessary destructor
std::ostream & operator<<(std::ostream & os, const stringbad & st)
stringbad::stringbad(const stringbad &st)
stringbad & stringbad::operator=(const stringbad st)
main檔案:vegnews.cpp -- using new and delete with classes
// compile with strngbad.cpp
#include
using std::cout;
#include "stringbad.h"
void callme1(stringbad &); // pass by reference
void callme2(stringbad &); // pass by value
int main()
void callme1(stringbad & rsb)
void callme2(stringbad &sb)
標頭檔案:stringbad.h
// strngbad.h -- flawed string class definition
#ifndef strngbad_h_
#define strngbad_h_
#include
class stringbad
;#endif
c 中的引用的使用原理以及使用例項 (1)
先看理論的東西,這個是我在網上搜尋到的,看來覺得比較不錯 這個部分是轉貼哦!引用是c 引入的新語言特性,是c 常用的乙個重要內容之一,正確 靈活地使用引用,可以使程式簡潔 高效。我在工作中發現,許多人使用它僅僅是想當然,在某些微妙的場合,很容易出錯,究其原由,大多因為沒有搞清本源。故在本篇中我將對引...
c 中引用符合的使用
對乙個資料建立乙個 引用 他的作用是為乙個變數起乙個別名。這是c 對c語言的乙個重要補充。如何建立乙個引用 int a 5 int b a cout以上宣告了b是a的引用,並把a,b的值和它們的位址列印出來。經過宣告後b是a別名,b與a代表的是同乙個變數,佔記憶體中同乙個儲存單元,具有同一位址。注意...
C 中引用的使用總結
1引用的定義 引用時c 對c的乙個重要的擴充,引用的作用是給變數起乙個別名。例如 int a int b a 宣告b是a的引用 經過以上的宣告,b就成為了a的別名,a和b的地位以及作用都是一樣的。將b宣告為a的引用,不需要再為b開闢新的單元,b和a在記憶體中佔同一儲存單元,它們具有相同的位址。複製 ...