c++禁止函式的傳值呼叫的方法
程式碼編譯執行環境:VS2017+Debug+Win32
按照引數形式的不同,C++應該有三種函式呼叫方式:傳值呼叫、引用呼叫和指標呼叫。對於基本資料型別的變數作為實參進行引數傳遞時,採用傳值呼叫與引用呼叫和指標呼叫的效率相差不大。但是,對於類型別來說,傳值呼叫和引用呼叫之間的區別很大,類物件的尺寸越大,這種差別越大。
傳值呼叫與後面兩者的區別在於傳值呼叫在進入函式體之前,會在棧上建立一個實參的副本,而引用和指標呼叫沒有這個動作。建立副本的操作是利用拷貝建構函式進行的。因此,要禁止傳值呼叫,就必須在類的拷貝建構函式上做文章。
可以直接在拷貝建構函式中丟擲異常,這樣就迫使程式設計師不能使用拷貝建構函式,否則程式總是出現執行時錯誤。但是,這不是一個好的辦法,應該在編譯的階段就告訴程式設計師,不能使用該類的拷貝建構函式。
1.不顯示定義拷貝建構函式可行嗎?
#include <iostream> using namespace std; class A { public: int num; A(){num=5;} }; void show(A a) { cout<<a.num<<endl; } int main() { A obj; show(obj); }
以上程式順利通過編譯,並輸出5。因此,不顯示定義拷貝建構函式,並不能阻止對類的拷貝建構函式的呼叫,原因是編譯器會自動為沒有顯示定義拷貝建構函式的類提供一個預設的拷貝建構函式。
2.顯示定義拷貝建構函式並將訪問許可權設定為private
上面的程式新增拷貝建構函式的定義,修改如下。
#include <iostream> using namespace std; class A { A(const A&){}; public: int num; A(){num=5;} }; void show(A a) { cout<<a.num<<endl; } int main() { A obj; show(obj); }
這個程式在VS2017環境下編譯不通過,得到如下錯誤:error C2248: “A::A”: 無法訪問 private 成員(在“A”類中宣告)。
void show(const A& a) { cout<<a.num<<endl; }
3.拷貝建構函式的說明
(1)如果將拷貝建構函式中的引用符號去掉&,編譯將無法通過,出錯的資訊如下:非法的複製建構函式: 第一個引數不應是“A”。原因是如果拷貝建構函式中的引數不是一個引用,即形如A(const A a),那麼就相當於採用了傳值的方式(pass-by-value),而傳值的方式會呼叫該類的拷貝建構函式,從而造成無窮遞迴地呼叫拷貝建構函式。因此拷貝建構函式的引數必須是一個引用或一個指標。
(2)拷貝建構函式的引數通常情況下是const的,但是const並不是嚴格必須的。
(3)附帶說明,在下面幾種情況下會呼叫拷貝建構函式:
a. 顯式或隱式地用同類型的一個物件來初始化另外一個物件;
b. 作為實參以值傳遞的方式傳遞給一個函式;
c. 在函式體內返回一個物件時,也會呼叫返回值型別的拷貝建構函式;
d. 需要產生一個臨時類物件時(類物件作為函式返回值會建立臨時物件)。
以上就是c++禁止函式的傳值呼叫的方法的詳細內容,更多關於c++禁止函式的傳值呼叫的資料請關注我們其它相關文章!