构造函数与赋值函数

本文详细介绍了C++中的拷贝构造函数、拷贝赋值、右值引用以及移动语义,包括移动构造函数和移动赋值的特点,以及它们在函数参数传递和对象初始化中的应用。作者还提到了移动构造过程中处理指针的问题和移动赋值的简单理解。
摘要由CSDN通过智能技术生成
拷贝构造与拷贝赋值

调用拷贝构造函数主要有以下场景:

  1:对象作为函数的参数,以值传递的方式传给函数。

  2:对象作为函数的返回值,以值的方式从函数返回。

  3:使用一个对象给另一个对象初始化。

构造 就是产生了新的对象;

赋值 是 已有对象改变他的值;

#include<iostream>

class Person1 {
private:
    std::string name;
    int age;
public:
    Person1(){}
    Person1(const char* name, int age) { this->name = name; this->age = age; }
    ~Person1(){}
    //Person1(const Person1& p) { this->name = p.name; this->age = p.age; std::cout << "构造" << std::endl; }//拷贝构造函数
    //Person1& operator=(const Person1& p) { this->name = p.name; this->age = p.age; std::cout << "赋值"; return *this; }//拷贝赋值函数
    void view() { std::cout << age;  }

};

int main() {

    Person1 xm("xm", 18);
    Person1 lm = xm;//调用拷贝构造函数 
    Person1 mn;
    mn = xm;//调用赋值构造函数
    lm.view();
}

注释的那两行去掉试一下就是这两个函数 ;

右值引用和移动语义

拷贝,顾名思义,产生新的对象,而原有对象不变。这增加了多余的操作;

移动 就是 直接把某个对象的所有权 直接转让给某个调用。不产生临时对象。比如在计算机中移动文件的场景,实际文件还停留在原来位置,只是修改了记录。

c++11新增了右值引用和移动语义(为了移动构造做铺垫)

对于大多数程序员来说,右值引用带来的好处并不是让我们能够编写使用右值引用的代码,而是弄够利用右值引用来实现移动语义的库代码。例如,STL类都有我们提到的这四个函数。

介绍一下什么是右值与左值

int x; //左值 

int y = x+z;(x+z)为右值

右值引用 可关联到右值 比如

int y = x+z;y关联的是当时计算的x+y的结果,即使以后修改了x,z的值,也不会影响y。

将右值关联到右值引用将导致该右值被储存到特定的位置,且可以获取该位置的地址。也就是说,int &&r1 = 13来说 我们虽然不可以将&作用在13上,但是可以用在r1上。通过将数据与特定的地址关联,使得可以通过右值引用来访问该数据。(这就对应了上述让出所有权,实现移动)

实现移动语义是引入右值引用的主要目的。

移动构造和移动赋值

对于移动构造函数的原型

Person1( Person1 && p);

这时 我们的参数传递为一个右值

#include<iostream>

class Person1 {
private:
    std::string name;
    int age;
public:
    Person1(){}
    Person1(const char* name, int age) { this->name = name; this->age = age; }
    ~Person1(){}
    Person1(const Person1& p) { this->name = p.name; this->age = p.age; std::cout << "构造" << std::endl; }//拷贝构造函数
    Person1& operator=(const Person1& p) { this->name = p.name; this->age = p.age; std::cout << "赋值"<<std::endl; return *this; }//拷贝赋值函数
    int view() { std::cout << age; return age; }
    Person1(Person1 && p) noexcept { this->name = p.name; this->age = p.age; p.age = 0; p.name = ""; std::cout << "移动构造" << std::endl;  }
    Person1 operator = (Person1&& p) noexcept { if (this == &p)return *this; this->age = p.age; p.age = 0; p.name = ""; std::cout << "移动赋值" << std::endl; return *this; }
    Person1 operator +(Person1 p) noexcept { this->age = this->age + p.age; std::cout << "+"; return *this; }

};

int main() {


    Person1 xa("xa", 11);
    Person1 xb("xb", 22);
    Person1 xc  (std::move(xa + xb));
    xc.view();


}

受版本影响 加了 std::move()这是强制语义转化,正常不用加。这个函数是将左值强制转化为右值。受左右值的影响,编译器才能区分何时用复制构造,何时用移动构造。

另外,我举得这个例子其实不是太好。如果移动构造过程中,4原对象有指针。那么,移动构造函数中要把指针指向nullptr。并在析构函数中释放掉它。

对于移动赋值,也就很好理解了。

例子并不好,希望大家自己改一改。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值