代码编译运行环境: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”类中声明)。
这样就能阻止了函数调用时,类A的对象以值传递的方式进行函数函数调用。为使程序通过编译,需将show()函数的定义改为如下形式:
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++禁止函数的传值调用的资料请关注自由互联其它相关文章!