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++笔记之移动构造函数何时会被调用,何时不会被调用

  • 相关阅读:
    Eclipse汉化教程
    php课程---文件操作及文件上传的代码总结
    php课程---Json格式规范需要注意的小细节
    php课程---php使用PDO方法详解(转)
    php课程---随机数
    php课程---Ajax(老师详解)
    php课程---JavaScript与Jquery的区别
    php课程---JavaScript与Jquery的区别(转)
    php课程---初学PDO
    php课程---练习(联系人信息表)
  • 原文地址:https://www.cnblogs.com/sunbines/p/9068987.html
Copyright © 2011-2022 走看看