您的位置:首页 > 编程语言 > C语言/C++

C++之拷贝构造函数

2013-12-26 16:06 218 查看
问题1:赋值构造函数和拷贝构造函数有什么不同?

作用:创建一个对象的同时,使用一个已经存在的对象给另一个对象赋值
做比较:拷贝构造函数:对象被创建 + 用一个已经存在的对象 进行初始化
拷贝赋值函数:对象已经存在不用创建 + 用一个已经存在的对象进行赋值

(区分开初始化操作和赋值)

举例:string a("hello");//调用构造函数
string b("would");//调用构造函数
string c=a;//调用拷贝构造函数--风格差,应使用string c(a)
c=b;//调用赋值构造函数
问题2:何时调用拷贝构造函数?
用一个已经存在的对象去初始化另一个对象,这时系统会自动调用拷贝构造函数
总结:1、拷贝构造函数的参数必须是引用,否则出错。
2、执行的语句类似 Coord p=p1; 则会调用拷贝构造函数
有三种情况:
1)创建一个新类 + 并使用类的一个对象初始化该类的另一个对象
Coord p2(p1);//用对象p1初始化对象p2
Coord p3=p1;//用对象p1初始化对象p1
2)函数的形参是类的对象 + 参数使用值传递(参数为引用的时候不调用拷贝构造函数),传参时,会调用拷贝构造函数

fun1(Coord p)
{
    函数体
}
调用语句:
Coord p1;
fun1(p1);
//分析:调用拷贝构造函数 Coord p=p1;

fun1(Coord& p)
{
    函数体
}
调用语句:
Coord p1;
fun1(p1);


//分析:参数表中使用了引用,没有调用拷贝构造函数啊,执行 Coord& p=p1;

3)函数的返回值是对象,函数调用完毕,返回调用者时,会调用拷贝构造函数

Coord fun1(Coord& fun)
{
    return fun;
}

调用语句:
Coord  c;
Coord p=fun(c);


//分析:return fun调用两次拷贝构造函数; VC测试,但是VS2005只调用一次,应该是进行了优化

Coord& fun1(Coord& fun1)
{  
    return fun1;
}

调用语句:
Coord  c;
Coord p=fun1(c);


// 分析:Coord p=fun1(c)调用一次拷贝构造函数,因为最后使用返回函数引用,return时没有借助临时对象变量,直接是 Coord p=fun1; 出现这种现象的原因:
1、在使用return返回一个对象时,系统是先申请一个临时对象temp,
执行Coord temp=fun1;(调用一次拷贝构造函数)
之后在执行Coord p=temp;(第二次调用)
2、在使用返回函数引用时,系统不会申请临时对象,只是直接把fun1拷贝给p
即直接执行Coord p=fun1,而没有引入temp,故少用一次拷贝构造函数
注意:这时要注意一个常出现的错误,返回的值不能是一个临时变量,常常的解决办法是函数参数使用引用,之后在使用return返回即可
问题3:怎么使用拷贝构造函数?
语法:函数名与类名相同,参数为本对象的引用,无返回类型,一个类中只有一个拷贝构造函数
类名::类名(类名& 对象名)
{拷贝成员}
代码:

class Point
{
public:
    Point(int xx=0,int yy=0){X=xx; Y=yy;}
    Point(Point&  p);
private:
    int  X,Y;
};
Point::Point (Point& p)
{
    X=p.X; //参数p可以直接引用私有变量
    Y=p.Y;
}


注意:参数必须为本对象的引用 + 类的函数体内参数可以直接使用本类中定义的私有变量(老忘)
常见问题:
1、为什么拷贝函数的参数必须是引用?(拷贝构造函数的参数必须是对象的引用)
简单点说,为了避免递归。
具体来说,使用那个引用传递的时候并不调用拷贝构造函数 而 值传递需要调用拷贝构造函数
所以,在进入拷贝构造函数时,需要把对象传进来,这时使用值传递还要再调一次拷贝构造函数.....这时要无限传递下去
2、浅拷贝与深拷贝
在类中添加成员变量char*p ,编写带参构造函数,参数为char* sz,并将sz赋值给p。
出现这个问题的原因:构造函数中需要为指针动态申请内存空间
深拷贝:在拷贝构造函数中,为指针显式的申请空间
浅拷贝:在拷贝构造函数中,仅仅使用成员间的对应复制,两个对象的指针的都指向同一个空间,一个指针 指向的空间被释放,再用另一个指针去访问被释放掉的空间,将会导致程序崩溃。
解决方法:如果构造函数需要为类显示申请空间(含指针,使用new),则要使用显式的拷贝构造函数,如果类中成员都是非指针,则可以使用系统默认的拷贝构造函数。
浅拷贝代码
  

#include <iostream>
#include <string>
using namespace std;
class Point
{
private:
    char * name;
public:
    Point(char * className)
    {
        name = new char[strlen(className)+1];
        strcpy(name, className);
    }
     Point(Point& p)//浅拷贝,或者不写
     {
         name = p.name;//(系统默认拷贝函数执行的代码)
     }
    ~Point()
    {
        cout<<name<<endl;//测试关键语句
        delete []name;
    }
};

int main()
{
    Point a("123");
    Point b=a;
    return 0;
}


深拷贝:



#include <iostream>
#include <string>
using namespace std;
class Point
{
private:
    char * name;
public:
    Point(char * className)
    {
        name = new char[strlen(className)+1];
        strcpy(name, className);
    }
    Point(Point& p)//深拷贝
    {
        name = new char[strlen(p.name)+1];
        strcpy(name,p.name);
    }
    ~Point()
    {
        cout<<name<<endl;
        delete []name;
    }
};

int main()
{
    Point a("123");
    Point b=a;
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: