c++primer 13.1-13.13

13.1
拷贝构造函数:构造函数写法,第一个参数为自身类类型的引用,,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
使用节点,拷贝初始化时候使用拷贝构造函数 ps:我觉得其实这里不仅仅我们自己定义的类需要定义拷贝构造函数,基本我们平时见过的所有类型,所有类都具有拷贝构造函数,不知不觉我们就会使用拷贝初始化,例如:

int  a = 5;
int b(a);

13.2
错误在于第一个参数必须引用,

13.3
拷贝一个StrBlob时候原StrBolb的所以数据都会拷贝过来,但是,需要注意的是,StrBlob对象的私有属性是有shared_ptr的,所以会将原shared_ptr的引用值加1,这是要注意的点,
拷贝StrBlob的时候由于指针是weak_ptr,是属于弱连接,所以被引用的StrBlob对象的智能指针不会增加引用次数,正常拷贝,没啥特别发生的

13.4

Point global;
Point foo_bar(Point arg) // 1,foo参数非引用,所以使用的时候是拷贝构造函数(以下简称拷贝)
{
     Point local = arg, *heap = new Point(global); // 2:local的构造非引用,所以是拷贝,*heap指向的内存要从global拷贝
     *heap = local; //3,*heap指向的内存需要重新从local进行拷贝过来
     Point pa[4] = { local, *heap }; // 4,pa[4]需要从 local和*heap指向的内存拷贝过来
     return *heap;  // 5,返回的是指向的一块内存,也不是引用,所以需要拷贝
}

13.5

 HasPtr(const HasPtr &a):ps(new std::string(*a.ps)),i(a.i){}

解释一下

ps(new std::string(a.ps));

ps指向自己新分配的string内存 就是

ps(new std::string())

拷贝内容是
*a.ps,放好位置就是 ps(new std::string(*a.ps))
这里注意,拷贝ps本身的话就是ps(new std::string(a.ps)),这样是不能通过编译的,因为咱申请的是string类型的内存,但是
a.ps是指针类型,试问指针类型怎么放入 string的内存呢

13.6
拷贝赋值运算符就是拷贝的时候进行赋值的,字面理解,当自己的类没有定义的时候,编译器会生成一个合成拷贝赋值运算符
作用: 合成拷贝赋值运算符:(以 operator=为例子)一般用来将运算符右侧的运算对象的每个非static的成员赋予它左侧运算对象的对应成员,这以工作是通过成员类型的拷贝赋值运算符来完成的。
拷贝赋值运算符就是基本所有类型都有的,用于拷贝对象的时候的运算。。好像可以这里么理解,当然,如果需要自己定义的话,什么符号都可以,<也可可以定义成为拷贝赋值运算符
13.7
从这一节小节的意义来讲,就是成员依次使用拷贝赋值运算符进行拷贝,但是还是那个问题,StrBlob使用的是shared_ptr指针,引用加一,拷贝StrBlobPtr的时候由于是weak_ptr指针,所以饮用不会增加
13.8

class HasPtr{
public:
    HasPtr(const std::string &s = std::string()):ps(new std::string(s)),i(0){}
    HasPtr(const HasPtr &a):ps(new std::string(*a.ps)),i(a.i){}
    HasPtr & operator=(const HasPtr &js){
        auto newp = new std::string(*js.ps);
        delete ps;
        ps = newp;
        i = js.i;
        return *this;//返回该对象
    }
private:
    std::string *ps;
    int i;
};

13.9
析构函数是~类名(){}函数,注意{}后还会隐式的执行对象成员的销毁过程
析构函数通俗来说就时用来销毁对象,释放对象所占用的内存的,而合成析构函数有时候被用来阻止该类型的对象被销毁
一个类没有定义自己的析构函数的时候,编译器就会为它定义一个合成析构函数
13.10
StrBlob对象销毁的时候share_ptr指针引用次数减一,若是变成零,指向的vector内存空间销毁 ,别的成员函数按照初始化顺序逆向销毁
StrBlobPtr对象销毁的时候成员按照初始化顺序逆向销毁,weak_ptr指针销毁时不影响内存销毁与否,不影响shared_ptr引用计数
13.11

    ~HasPtr(){}

13.12
三次

bool fcn(const Sales_data *trans, Sales_data accum)//这里的第二个参数,是在参数列表初始化的,执行完函数被销毁
{
    Sales_data item1(*trans), item2(accum);//item1,item2执行完函数被销毁
    return item1.isbn() != item2.isbn();
}

13.13

#include 
#include 
#include
class Sale_data{
public:
    Sale_data(const Sale_data &);
private:
    std::string bookNo;
    int units_sold = 0;
    double revence = 0.0;
};
Sale_data::Sale_data(const Sale_data& sa):bookNo(sa.bookNo),units_sold(sa.units_sold),revence(sa.revence){}



class HasPtr{
public:
    HasPtr(const std::string &s = std::string()):ps(new std::string(s)),i(0){}
    HasPtr(const HasPtr &a):ps(new std::string(*a.ps)),i(a.i){}
    HasPtr & operator=(const HasPtr &js){
        ps = new std::string(*js.ps);
        i = js.i;
        return *this;
    }
    ~HasPtr(){}
private:
    std::string *ps;
    int i;
};


struct test{
    test(int a):value(a){
        std::cout<<"单参数数默认构造函数"< ivec){
    ivec.push_back(a);
}
void use2(test b,std::vector ivec){
    ivec.push_back(b);
}
int main()
{
   std::vector vec;
   test li(6);//单参构造
   test a(10);//单参构造
   li =a;//拷贝赋值运算符
   test *x = new test;//无参数默认构造函数
   use1(*x,vec);//此方法为引用,所以是直接在vector中使用拷贝构造函数
   use2(*x,vec);//此方法非引用,先拷贝构造一个*x的副本,再在vector中拷贝构造一个副本的副本
   delete x;//销毁x指向的内存(test对象),执行析构函数
   return 0;//将存在的test对象都销毁
}

你可能感兴趣的:(c++primer 13.1-13.13)