关于复制构造函数

也许很多C++的初学者都知道什么是构造函数,但是对复制构造函数(copy constructor)却还很陌生。对于我来说,在写代码的时候能用得上复制构造函数的机会并不多,不过这并不说明复制构造函数没什么用,其实复制构造函数能解决一些我们常常会忽略的问题。

       为了说明复制构造函数作用,我先说说我们在编程时会遇到的一些问题。对于C++中的函数,我们应该很熟悉了,因为平常经常使用;对于类的对象,我们也很熟悉,因为我们也经常写各种各样的类,使用各种各样的对象;对于指针的操作,我们也不陌生吧?嗯,如果你还不了解上面三个概念的话,我想这篇文章不太适合你,不过看看也无碍^_^。我们经常使用函数,传递过各种各样的参数给函数,不过把对象(注意是对象,而不是对象的指针或对象的引用)当作参数传给函数的情况我们应该比较少遇见吧,而且这个对象的构造函数还涉及到一些内存分配的操作。嗯,这样会有什么问题呢?

       把 参数传递给函数有三种方法,一种是值传递,一种是传地址,还有一种是传引用。前者与后两者不同的地方在于:当使用值传递的时候,会在函数里面生成传递参数 的一个副本,这个副本的内容是按位从原始参数那里复制过来的,两者的内容是相同的。当原始参数是一个类的对象时,它也会产生一个对象的副本,不过在这里要 注意。一般对象产生时都会触发构造函数的执行,但是在产生对象的副本时却不会这样,这时执行的是对象的复制构造函数。为什么会这样?嗯,一般的构造函数都 是会完成一些成员属性初始化的工作,在对象传递给某一函数之前,对象的一些属性可能已经被改变了,如果在产生对象副本的时候再执行对象的构造函数,那么这 个对象的属性又再恢复到原始状态,这并不是我们想要的。所以在产生对象副本的时候,构造函数不会被执行,被执行的是一个默认的构造函数。当函数执行完毕要 返回的时候,对象副本会执行析构函数,如果你的析构函数是空的话,就不会发生什么问题,但一般的析构函数都是要完成一些清理工作,如释放指针所指向的内存 空间。这时候问题就可能要出现了。假如你在构造函数里面为一个指针变量分配了内存,在析构函数里面释放分配给这个指针所指向的内存空间,那么在把对象传递 给函数至函数结束返回这一过程会发生什么事情呢?首先有一个对象的副本产生了,这个副本也有一个指针,它和原始对象的指针是指向同块内存空间的。函数返回 时,对象的析构函数被执行了,即释放了对象副本里面指针所指向的内存空间,但是这个内存空间对原始对象还是有用的啊,就程序本身而言,这是一个严重的错 误。然而错误还没结束,当原始对象也被销毁的时候,析构函数再次执行,对同一块系统动态分配的内存空间释放两次是一个未知的操作,将会产生严重的错误。

       上 面说的就是我们会遇到的问题。解决问题的方法是什么呢?首先我们想到的是不要以传值的方式来传递参数,我们可以用传地址或传引用。没错,这样的确可以避免 上面的情况,而且在允许的情况下,传地址或传引用是最好的方法,但这并不适合所有的情况,有时我们不希望在函数里面的一些操作会影响到函数外部的变量。那 要怎么办呢?可以利用复制构造函数来解决这一问题。复制构造函数就是在产生对象副本的时候执行的,我们可以定义自己的复制构造函数。在复制构造函数里面我 们申请一个新的内存空间来保存构造函数里面的那个指针所指向的内容。这样在执行对象副本的析构函数时,释放的就是复制构造函数里面所申请的那个内存空间。

       除了将对象传递给函数时会存在以上问题,还有一种情况也会存在以上问题,就是当函数返回对象时,会产生一个临时对象,这个临时对象和对象的副本性质差不多。

       关于复制构造函数的性质还有很多,不过一时说不清楚,头脑还比较乱。^_^

       C++真是复杂,不过复杂得来还挺有意思。

       C++真是复杂,不过复杂得来还挺有意思。

    

      感觉自己的表达能力还很欠缺,我自己是比较明白什么是复制构造函数以及它的作用的,但是这篇文章却说得不清不楚.一般来说程序员都有很强的思维逻辑能力,但在表达能力方面还是需要锻炼的.也许多写写类似的文章能够改善自己在表达这一方面的能力吧.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是关于stack复制构造函数的介绍: 在C++中,复制构造函数是一种特殊的构造函数,它在创建对象时使用另一个相同类型的对象来初始化新对象。当我们使用一个对象去初始化另一个对象时,复制构造函数就会被调用。对于stack来说,复制构造函数用于创建一个新的stack对象,并将其初始化为另一个stack对象的副本。 下面是一个示例代码,展示了如何定义一个stack的复制构造函数: ```c++ #include <iostream> #include <stack> using namespace std; class MyStack { private: int* arr; int top; int capacity; public: // 默认构造函数 MyStack(int size = 10) { arr = new int[size]; capacity = size; top = -1; } // 复制构造函数 MyStack(const MyStack& other) { capacity = other.capacity; top = other.top; arr = new int[capacity]; for (int i = 0; i <= top; i++) { arr[i] = other.arr[i]; } } // 析构函数 ~MyStack() { delete[] arr; } // 入栈 void push(int x) { if (top == capacity - 1) { cout << "Stack Overflow" << endl; return; } arr[++top] = x; } // 出栈 void pop() { if (top == -1) { cout << "Stack Underflow" << endl; return; } top--; } // 返回栈顶元素 int peek() { if (top == -1) { cout << "Stack is Empty" << endl; return -1; } return arr[top]; } // 判断栈是否为空 bool isEmpty() { return top == -1; } // 返回栈的大小 int size() { return top + 1; } // 打印栈中的元素 void printStack() { if (top == -1) { cout << "Stack is Empty" << endl; return; } for (int i = top; i >= 0; i--) { cout << arr[i] << " "; } cout << endl; } }; int main() { MyStack s1(5); s1.push(1); s1.push(2); s1.push(3); s1.push(4); s1.push(5); MyStack s2 = s1; // 复制构造函数被调用 s1.pop(); s2.pop(); cout << "s1: "; s1.printStack(); cout << "s2: "; s2.printStack(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值