zoukankan      html  css  js  c++  java
  • 移动构造函数

     1 #include<iostream>
     2 #include<vector>
     3 #include<string>  
     4 using namespace std;
     5 
     6 class Test
     7 {
     8 public:
     9     Test(const string& s = "hello world") :str(new string(s)) { cout << "默认构造函数" << endl; };
    10     Test(const Test& t);
    11     Test& operator=(const Test& t);
    12     Test(Test&& t) noexcept;
    13     Test& operator=(Test&& t) noexcept;
    14     ~Test();
    15 public:
    16     string * str;
    17 };
    18 
    19 Test::Test(const Test& t)
    20 {
    21     str = new string(*(t.str));
    22     cout << "拷贝构造函数" << endl;
    23 }
    24 Test& Test::operator=(const Test& t)
    25 {
    26     cout << "拷贝赋值运算符" << endl;
    27     return *this;
    28 }
    29 Test::Test(Test&& t)noexcept
    30 {
    31     str = t.str;
    32     t.str = nullptr;
    33     cout << "移动构造函数" << endl;
    34 }
    35 Test& Test::operator=(Test&& t)noexcept
    36 {
    37     cout << "移动赋值运算符" << endl;
    38     return *this;
    39 }
    40 Test::~Test()
    41 {
    42     cout << "析构函数" << endl;
    43 }
    44 
    45 int main()
    46 {
    47     vector<Test> vec(1);
    48     Test t("what");
    49     vec.push_back(std::move(t));
    50     return 0;
    51 }

    运行结果:

    首先说说为什么会这样输出:

    1、第一个 “默认构造函数” 是因为vector<Test> vec(1) , 所以事先使用默认构造函数构造了一个Test对象

    2、第二个 “默认构造函数” 是因为Test t ,使用默认构造函数构造了一个对象

    3、第三个 “移动构造函数” 大多数人会以为是 vec.push_back(std::move(t)) ,push_back 导致对象的移动而输出的。具体的原因其实是由于重新分配内存而导致的,我们的 vector 对象 vec 初始的容量只有 1 ,且里面已经有一个对象了,就是vector<Test> vec(1)的时候创建的,所以再向vec里面添加Test对象时,就会导致vec重新分配内存。由于vec中的对象定义了移动构造函数且是可用的(因为我们将其声明为了noexcept),所以就会调用移动构造函数将vec中原始的那个对象移动到新的内存中,从而输出 “移动构造函数”。

    4、第四个 “移动构造函数” 才是因为Test 对象 t 被移动到vector 对象 vec 新的空间而输出的

    5、第五个 “析构函数” 是因为重新分配内存后,原来的内存将被销毁,所以输出一个“析构函数”

    6、后面三个 “析构函数” 是因为执行了return 0, 内存被释放,vec 和 t 都被析构,所以输出三个 “析构函数”

    将 Test.h 和 Test.cpp 文件中的noexcept 都删去,输出的结果变成了:

    更改之后的输出只有第四行的输出变了,其余行输出原因与上面是一样的

    第四行的输出由 “移动构造函数” 变成了 “拷贝构造函数” ,原因是:

    由于我们的移动构造函数没有声明为noexcept,所以我们的移动构造函数就会被认为是可能抛出异常,所以在重新分配内存的过程中,vec 对象就会使用拷贝构造函数来“移动”对象(这里说的移动其实是拷贝,并不是移动),所以就输出了“拷贝构造函数”。

    参考资料

    1. C++笔记之移动构造函数何时会被调用,何时不会被调用

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 矩阵加法
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 乘法表
    监管只是压倒网盘业务的一根稻草,但不是主要原因(答案只有一个:成本!)
  • 原文地址:https://www.cnblogs.com/sunbines/p/9068987.html
Copyright © 2011-2022 走看看