c++之类在函数参数、返回值和赋值运算时的传递方式

本文探讨了C++中类在作为函数参数、返回值和赋值运算时的传递方式,强调了在类成员包含指针时可能出现的问题。通过实例分析了拷贝构造函数、赋值运算符重载以及引用的使用,解释了如何防止多重释放和隐藏的bug。建议自定义拷贝构造函数和赋值运算符,或使用引用来避免潜在风险。
摘要由CSDN通过智能技术生成

类在函数参数、返回值和赋值运算时的传递方式




参考资料:

  • c++拷贝构造函数详解:https://www.cnblogs.com/alantu2018/p/8459250.html
  • C++:类中的赋值函数:https://www.cnblogs.com/duwenxing/p/7445927.html
  • C/C++ 引用作为函数的返回值:https://blog.csdn.net/weixin_40539125/article/details/81410008
  • C++ 指针的引用和指向引用的指针:https://blog.csdn.net/fatfish_/article/details/86768887
  • C++临时变量的生命周期:https://www.cnblogs.com/catch/p/3251937.html
  • [c++11]我理解的右值引用、移动语义和完美转发:https://www.jianshu.com/p/d19fc8447eaa
  • 《C++ Primer Plus》

类除了默认构造函数与默认析构函数外,还有默认拷贝函数和默认赋值函数。

而函数在按值传递参数和返回值的时候,会先通过拷贝的方式创建临时变量(类似test T2(T1);),用作形参和返回值。引用参考文献的话:临时变量的作用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束,也就是在语句T2 = fn3(T1);之后)。

正如《C++ Primer Plus》提到的,引用更接近const指针(都需要创建时初始化)。所以函数按引用传递参数和返回值的时候,不会创建临时变量,也没有上述的拷贝过程。


所以当类作为函数参数或返回值的时候,如果需要创建临时变量,会调用默认拷贝函数(默认直接复制所有类成员)。一般情况下这样做没什么,但是如果类数据成员有指针的话,就会出现如下等价情况

  T3.p = new int(985);
  T4.p = T3.p;

然后T3与T4在各自的作用域结束时会被析构,在T3中,由于使用了new创建内存,所以析构函数里需要

  delete p;

同理T4时T3的完整复制,所以T4有相同的析构函数,所以析构时会出现以下等价情况

  delete T3.p;
  delete T4.p;

因为大多数编译器也不会报错,所以这样会造成致命的隐藏bug。(个人猜想第一次delete释放了不该释放的内存,第二次delete可能造成数据错乱)


同理,把函数返回值赋值给别的类时,也会调用默认赋值函数。和默认拷贝函数一样,也是直接复制所有类成员,同样是如果数据成员有指针的话,会触发以上隐藏bug



那么具体操作时如何避免以上问题呢,我们先看如下例子,再慢慢解释

// test.h

// 防止头文件重包含
#ifndef test_h
#define test_h

#include <assert.h>
#include <iostream>

using namespace std;

class test_empty {};

class test {
 private:
  double weight = 3.0;

 public:
  double area = 9.0;
  int* p = NULL;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值