拷贝构造函数定义时未加const修饰形参

前言

最近复习c++中,类相关的知识。在做默认构造和拷贝构造相关实验的过程中,遇到了一个很疑惑的问题。后来才发现,是由于编写的时候语法不规范导致的(不应该被修改的实参,引用形式传入时加const限定)。所以在这里记录一下,如果有其他小伙伴遇到了,也能作一个提醒。

问题描述以及解决方案

在visual studio中,定义了如下的拷贝构造函数以及重载运算符= 

class Complex{       //复数类的定义
public:
    Complex(Complex& c)   //拷贝构造    
    {
    	cout << "拷贝构造" << endl;
	    this->real = c.real;
	    this->image = c.image;
    }

    Complex& operator=(Complex& c)   //重载=
    {
    	cout << "重载=的调用" << endl;
    	this->real = c.real;
    	this->image = c.image;
    	return *this;
    }


private:
    double real;
    double image;
};

上面的代码,咋一看好像没什么问题,而且在visual c++ 6.0中,这样定义出来的拷贝构造函数和重载出来的=操作符是可以正常使用的。但是如果放在visual studio中,就会出现很诡异的错误。

首先是拷贝构造的问题:

### C++ 拷贝构造函数形参是否可以使用值传递及其原因 在 C++ 中,拷贝构造函数形参通常是常量引用类型(`const 类型&`),而不是值传递的形式。这是因为拷贝构造函数本身的设计目的是用来创建一个新的对象作为已有对象的副本。如果将其形参设置为值传递,则会产生递归调用的问题。 #### 值传递不可行的原因 假设我们将拷贝构造函数形参改为值传递形式,如下所示: ```cpp class MyClass { public: int value; // 构造函数 MyClass(int v) : value(v) {} // 错误的拷贝构造函数定义:值传递 MyClass(MyClass obj) { // 尝试使用值传递 value = obj.value; std::cout << "拷贝构造函数被调用" << std::endl; } }; ``` 在这种情况下,当尝试通过 `MyClass obj2(obj1)` 调用拷贝构造函数,会发生以下问题: - 参数 `obj` 是按值传递的,这意味着需要先创建一个临的对象来传递给形参。 - 创建这个临对象的过程又会触发拷贝构造函数的调用。 - 结果是无限递归调用拷贝构造函数,最终导致栈溢出并崩溃程序运行[^1]。 因此,为了避免这种递归行为,C++拷贝构造函数通常采用 **常量引用** (`const 类型&`) 或者普通的引用 (`类型&`) 来接收参数。这样既不会引起新的对象创建过程,也不会破坏原有对象的内容。 #### 使用引用的好处 使用引用作为形参的主要优势在于避免了不必要的对象复制操作,提高了效率的同还保持了原始对象的状态不变。特别是对于大型或复杂的对象来说,这种方式能够显著减少内存开销和计算间成本。 另外需要注意的是,在实际开发过程中,除了基本数据类型的简单赋值外,大多数候我们都希望保护原对象免受修改影响,所以一般推荐使用 `const` 关键字修饰引用变量,表明该引用所指向的内容不允许被改变[^3]。 --- ### 总结 综上所述,由于值传递会导致递归调用拷贝构造函数进而造成堆栈溢出的风险,所以在 C++拷贝构造函数形参不应该也不支持值传递方式。相反地,应当选用更安全高效的引用传参模式——即以 `const 类型&` 或者非 const 引用的方式声明其唯一正式参数。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值