Chinaunix首页 | 论坛 | 博客
  • 博客访问: 288560
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2008-09-02 12:43:19

拷贝构造函数(copy constructer),析构函数(destructer)和赋值运算符(assignment operator)(的重载)组成了拷贝控制(copy control)。
拷贝构造函数,通常只有一个参数,本类类型的const引用,用于:
1.显式或隐式的用已有对象的值来初始化一个新的对象。
2.复制一个对象,当作实参传递给函数。
3.复制一个对象作为函数参数的返回值。
4.用于初始化顺序容器的元素。
5.根据元素初始化列表初始化数组中的元素。

拷贝构造函数 should 使用初始化列表的方式进行成员"复制"。

string s("section13");//通过string类的构造函数直接给新对象s赋值
string s="section13";//先创建一个临时string对象,把section13赋值给它,再通过拷贝构造函数把临时对象的值赋值给s。
此两种方法导致的机器底层语言优化不同。
IO类型的对象不能用拷贝构造函数赋值。
非引用类型的函数参数与非引用类型的函数返回值都是复制后的。(如果是类类型的,就是调用了拷贝构造函数)

顺序容器的初始化中,vector vec[5],先创建一个临时对象,之后调用5次拷贝构造函数。
注:为了优化通常创建一个空的顺序容器,然后向其中加入想要的值,当然想用容器初始化后默认的值时例外。

当创建类类型的数组时,如果没有为类类型的数组提供元素初始化形式,调用的是默认构造函数;如果用常规的括号列表进行初始化,则调用的是拷贝构造函数。
这也就解释了在《c++学习笔记2-顺序容器的操作》中不解的地方。

#include <iostream>
using namespace std;

class s12{
public:
    s12():i(2){
        cout<<"in s12 constructor\n";
    }
    s12(s12 &obj){
        cout<<"in s12 copy constructor\n";
    }
    ~s12(){
        cout<<"in s12 destructor\n";
    }
    int i;
};
int func(s12 argu)
//s12 func(s12& argu)

{
    cout<<"argu.i:: "<<argu.i<<endl;
        }

//s12 func2();

int main(void) {
    //puts("Hello World!!!");

    s12 obj_s12;
    cout<<"obj_s12.i:: "<<obj_s12.i<<endl;
    s12 obj2=obj_s12;
    //obj_s12.~s12();

    cout<<"obj2.i:: "<<obj2.i<<endl;
    cout<<"in func\n";
    func(obj_s12);
    cout<<"end func\n";
    return EXIT_SUCCESS;
}

运行结果1为

in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
in s12 copy constructor
argu.i:: 29953184
in s12 destructor
end func
in s12 destructor
in s12 destructor

首先注意到在我们自己定义了拷贝构造函数后,通过“=”给obj2初始化赋值,调用的是定义的考构,在其中只有一条输出语句而无实际的复制,故obj_s12的i值并没有复制给obj2,obj2的i值是2293600,随机的。
在函数func中,形参为类s12类型的对象,不是引用,所以要对参数进行复制,再当作实参传进函数,故输出中在in func的下面看到了考构,在函数结束end func的上面看到将创建的临时对象析构。
我们将函数定义处改为传引用,其它不变。

int func(s12 &argu)

输出结果2为

in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
argu.i:: 2
end func
in s12 destructor
in s12 destructor

函数执行时就没有了对形参的复制。
我们再将函数改为

s12 func(s12& argu)
{
    cout<<"argu.i:: "<<argu.i<<endl;
    return argu;
    }

运行结果3为

in s12 constructor
obj_s12.i:: 2
in s12 copy constructor
obj2.i:: 2293600
in func
argu.i:: 2
in s12 copy constructor
in s12 destructor
end func
in s12 destructor
in s12 destructor

结果3与结果1不同在于结果3在函数体内输出argu.i后看到考构,因为此时函数的返回值是s12类型对象,非引用,需要调用考构创建一个临时对象将其返回。
如果将函数返回值改为s12 &,返回的是引用,则输出结果与结果2相同,函数内没有考构出现。
阅读(632) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~