拷贝,赋值构造函数赋值

拷贝构造函数:
构造函数的第一个参数必须是一个引用类型,且任何额外擦数都有默认值。
拷贝构造函数的第一个参数必须是一个引用类型,因为
拷贝构造函数被用来初始化非引用类类型参数。

拷贝初始化:
将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换。
拷贝初始化通常使用拷贝构造函数完成的。

拷贝构造函数在以下的情况会被调用:
1.拷贝初始化(用=定义变量)。
2.将一个对象作为实参传递给非引用类型的参数。
3.一个返回类型为非引用类型的函数返回一个对象。
4.用花括号初始化一个数组中的元素或一个聚合类中的成员
5.初始化标准容器或调用其insert/push操作时,容器会对其元素进行拷贝初始化

拷贝赋值运算符:
拷贝赋值运算符本身是一个重载的赋值运算符,定义为类的成员函数,左侧运算对象绑定到隐含的this参数,而右侧运算对象是所属类类型的,作为函数的参数,函数返回指向其左侧对象的引用。
当对类对象进行赋值时,会使用拷贝赋值运算。
通常情况下,合成的拷贝赋值运算符会将右侧对象的非static成员逐个赋予左侧对象的对应成员,这些赋值操作是由成员类型的拷贝赋值运算来完成的。
若一个类未定义自己的拷贝赋值运算符,编译器就会为其合成拷贝运算符。

#include <iostream>
#include <vector>
using namespace std;
class sales_item
{
public:
    sales_item() : units_sold(0), revenue(0.0)
    {
        cout << "默认构造函数被调用" << endl;
    }
    sales_item(const std::string &book) :
        bookno(book), units_sold(0), revenue(0.0)
    {
        cout << "构造函数被调用" << endl;
    }
    //与合成的拷贝构造函数等价的拷贝函数的声明
    sales_item(const sales_item &orig);
    sales_item& operator=(const sales_item &rhs);

private:
    std::string bookno;
    unsigned units_sold;
    double revenue = 0.0;
};
sales_item::sales_item(const sales_item &orig) :
bookno(orig.bookno), units_sold(orig.units_sold), revenue(orig.revenue)
{
    cout << "拷贝构造函数被调用" << endl;
}
sales_item fun(sales_item item)
{
    cout << "调用foo:"<<endl;
    sales_item temp;//调用默认构造函数
    temp = item;//拷贝赋值运算符被调用
    //从一个返回类型为非引用类型的函数返回一个对象
    return temp;
}

sales_item& sales_item::operator=(const sales_item &rhs)
{
    cout << "拷贝赋值运算符被调用" << endl;
    bookno = rhs.bookno;//调用string::operator=
    units_sold = rhs.units_sold;//使用内置的int赋值
    revenue = rhs.revenue;//使用内置的double赋值
    return *this;//返回一个队此对象的引用
}
    //如果我们不写拷贝构造函数和赋值赋值操作符构造函数的时候,系统会自动会为我们生成;
    //但是当一个类里面有数据成员有指针的时候,动态地分配了内存的时候,那就必须自己写了
class foo
{
public:
    //用指针p指向动态创建的字符串
    foo() :p(new std::string), a(0), b(0){
        cout << "foo的默认构造函数被调用了" << endl;
    }
    foo(const foo& other) :
        //通过P指针把字符串拿到,然后构建一个新的字符串,再把p初始化
        p(new std::string(*(other.p))), a(other.a), b(other.b)//如何使系统默认的则会写成p(obj.p)
    {
        cout << "foo的拷贝构造函数被调用" << endl;
    }
    foo& operator=(const foo &rhs)
    {
        cout << "foo的赋值操作符被调用" << endl;
        p = new std::string;
        *p = *(rhs.p);
        a = rhs.a;
        b = rhs.b;
        return *this;
    }
private:
    std::string *p;
    int a;
    double b;
};
int main()
{
    sales_item ret;//调用默认构造函数
    ret = fun(ret);//将一个对象作为实参传递给一个非引用类型的参数
    cout << endl;
    sales_item a = "9-999-9999-999";//拷贝构造函数,但是编译器会绕过拷贝构造函数
    //将sales_item a = "9-999-9999-999"变成sales_item a(9-999-9999-999);
    cout <<"数组"<< endl;
    sales_item primer_eds[]{
    string("2016-04-04"),
    string("2016-04-04"),
    string("2016-04-04"),
    };
    cout << "vector:" << endl;
    vector<sales_item> svec(5);
    cout << endl;
    foo x, y;
    foo z(x);
    x = y;
    return 0;
}

拷贝赋值运算符:

#include <iostream>
#include <vector>
using namespace std;
class sales_item
{
public:
    sales_item() : units_sold(0), revenue(0.0)
    {
        cout << "默认构造函数被调用" << endl;
    }
    sales_item(const std::string &book) :
        bookno(book), units_sold(0), revenue(0.0)
    {
        cout << "构造函数被调用" << endl;
    }
    //与合成的拷贝构造函数等价的拷贝函数的声明
    sales_item(const sales_item &orig);
    sales_item& operator=(const sales_item &rhs);

private:
    std::string bookno;
    unsigned units_sold;
    double revenue = 0.0;
};
sales_item::sales_item(const sales_item &orig) :
bookno(orig.bookno), units_sold(orig.units_sold), revenue(orig.revenue)
{
    cout << "拷贝构造函数被调用" << endl;
}
sales_item fun(sales_item item)
{
    cout << "调用foo:"<<endl;
    sales_item temp;//调用默认构造函数
    temp = item;//拷贝赋值运算符被调用
    //从一个返回类型为非引用类型的函数返回一个对象
    return temp;
}

sales_item& sales_item::operator=(const sales_item &rhs)
{
    cout << "拷贝赋值运算符被调用" << endl;
    bookno = rhs.bookno;//调用string::operator=
    units_sold = rhs.units_sold;//使用内置的int赋值
    revenue = rhs.revenue;//使用内置的double赋值
    return *this;//返回一个队此对象的引用
}
    //如果我们不写拷贝构造函数和赋值赋值操作符构造函数的时候,系统会自动会为我们生成;
    //但是当一个类里面有数据成员有指针的时候,动态地分配了内存的时候,那就必须自己写了
class foo
{
public:
    //用指针p指向动态创建的字符串
    foo() :p(new std::string), a(0), b(0){
        cout << "foo的默认构造函数被调用了" << endl;
    }
    foo(const foo& other) :
        //通过P指针把字符串拿到,然后构建一个新的字符串,再把p初始化
        p(new std::string(*(other.p))), a(other.a), b(other.b)//如何使系统默认的则会写成p(obj.p)
    {
        cout << "foo的拷贝构造函数被调用" << endl;
    }
    foo& operator=(const foo &rhs)
    {
        cout << "foo的赋值操作符被调用" << endl;
        p = new std::string;
        *p = *(rhs.p);
        a = rhs.a;
        b = rhs.b;
        return *this;
    }
private:
    std::string *p;
    int a;
    double b;
};
int main()
{
    sales_item ret;//调用默认构造函数
    ret = fun(ret);//将一个对象作为实参传递给一个非引用类型的参数
    cout << endl;
    sales_item a = "9-999-9999-999";//拷贝构造函数,但是编译器会绕过拷贝构造函数
    //将sales_item a = "9-999-9999-999"变成sales_item a(9-999-9999-999);
    cout <<"数组"<< endl;
    sales_item primer_eds[]{
    string("2016-04-04"),
    string("2016-04-04"),
    string("2016-04-04"),
    };
    cout << "vector:" << endl;
    vector<sales_item> svec(5);
    cout << endl;
    foo x, y;
    foo z(x);
    x = y;
    return 0;
}

赋值运算符和拷贝构造函数的区别与联系?
相同点:都是将一个对象拷贝到另一个中去。
不同点:拷贝构造函数涉及到要新建立一个对象。

#include <iostream>
#include <vector>
using namespace std;
class sales_item
{
public:
    sales_item() : units_sold(0), revenue(0.0)
    {
        cout << "默认构造函数被调用" << endl;
    }
    sales_item(const sales_item &orig) :
        bookno(orig.bookno), units_sold(orig.units_sold), revenue(orig.revenue)
    {}
    sales_item& operator=(const sales_item &rhs)
    {
        bookno = rhs.bookno;//调用string::operator=
        units_sold = rhs.units_sold;//使用内置的int赋值
        revenue = rhs.revenue;//使用内置的int赋值
        return *this;//返回一个队此对象的引用
    }

private:
    int bookno = 1;
    int units_sold = 2;
    int revenue = 3;
};
int main()
{
    sales_item a, b;
    sales_item c = b;
    a = c;
    return 0;
}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值