前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++如何禁止函数的传值调用

C++如何禁止函数的传值调用

作者头像
恋喵大鲤鱼
发布2019-02-22 11:33:52
2.4K0
发布2019-02-22 11:33:52
举报
文章被收录于专栏:C/C++基础C/C++基础

代码编译运行环境:VS2017+Debug+Win32


按照参数形式的不同,C++应该有三种函数调用方式:传值调用、引用调用和指针调用。对于基本数据类型的变量作为实参进行参数传递时,采用传值调用与引用调用和指针调用的效率相差不大。但是,对于类类型来说,传值调用和引用调用之间的区别很大,类对象的尺寸越大,这种差别越大。

传值调用与后面两者的区别在于传值调用在进入函数体之前,会在栈上建立一个实参的副本,而引用和指针调用没有这个动作。建立副本的操作是利用拷贝构造函数进行的。因此,要禁止传值调用,就必须在类的拷贝构造函数上做文章。

可以直接在拷贝构造函数中抛出异常,这样就迫使程序员不能使用拷贝构造函数,否则程序总是出现运行时错误。但是,这不是一个好的办法,应该在编译的阶段就告诉程序员,不能使用该类的拷贝构造函数。

1.不显示定义拷贝构造函数可行吗?

代码语言:javascript
复制
#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

上面的程序添加拷贝构造函数的定义,修改如下。

代码语言:javascript
复制
#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()函数的定义改为如下形式:

代码语言:javascript
复制
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. 需要产生一个临时类对象时(类对象作为函数返回值会创建临时对象)。


参考文献

[1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.[3.5(P102-P103)] [2]拷贝构造函数什么时候调用?

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年10月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.不显示定义拷贝构造函数可行吗?
  • 2.显示定义拷贝构造函数并将访问权限设置为private
  • 3.拷贝构造函数的说明
  • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档