美文网首页
C++ 11 新特性(七)

C++ 11 新特性(七)

作者: IT孤独者 | 来源:发表于2018-09-12 21:32 被阅读0次

今天任性,想写一个自己感兴趣的问题,move 语义。

先上代码

#include <iostream>

class A {
   public:
      A() {
         std::cout << "constructor A" << std::endl;
      }
      ~A() {
         std::cout << "destructor A" << std::endl;
      }
};

A func () {
   A a;

   return std::move(a);
}

int main() {
   auto a = func();

   std::cout << "flag 1" << std::endl;

   return 0;
}

问题是打印什么?

如果没有 move 语义,我想你一定知道打印什么,现在的问题是有了 move 之后,现在你还能知道吗?

上结果,然后说下原因

constructor A
destructor A
flag 1
destructor A

move 抵消了一次 constructor, 但是却出现了两次 destructor,这个和传统 C++ 是相悖的。那么现在有问题了,由于调用了两次 destructor 如何解决资源重复释放的问题?比如我在构造函数里面 new 了一个对象,需要在析构函数里面释放,这个问题怎么解决?

C++ 使用了一个 move constructor, 这个东西有点类似 copy constructor,代码如下:

#include <iostream>

class A {
   public:
      A() {
         std::cout << "constructor A" << std::endl;
      }
      ~A() {
         std::cout << "destructor A" << std::endl;
      }

      A( A & oth) {
         std::cout << "copy constructor A" << std::endl;
      }

      A(A && oth) {
         std::cout << "move constructor A" << std::endl;
      }
};

A func () {
   A a;

   return std::move(a);
}

int main() {
   A a = func();

   std::cout << "flag 1" << std::endl;

   return 0;
}

输出结果如下:

constructor A
move constructor A
destructor A
flag 1
destructor A

好了,资源释放的问题,我们就放到 move constructor 里面,为了对比,我写个 copy constructor 的过程,去除了所有可能的异常case,只是做个示范,代码如下:

#include <iostream>

class A {
   public:
      A() {
         std::cout << "constructor A" << std::endl;

         num = new int(100);
      }
      ~A() {
         if (num == nullptr) {
            std::cout << ">>>>num is nullptr" << std::endl;
         } else {
            std::cout << ">>>>num value is " << *num << std::endl;
            delete num;
         }
         std::cout << "destructor A" << std::endl;
      }

      A( A & oth) {
         std::cout << "copy constructor A" << std::endl;

         num = new int;

         num = oth.num;
      }

      A(A && oth) {
         std::cout << "move constructor A" << std::endl;

         num = std::move(oth.num);
         oth.num = nullptr;
      }

   public:
      int * num;
};

A func () {
   A a;

   return std::move(a);
}

int main() {
   A a = func();

   std::cout << "flag 1" << std::endl;

   return 0;
}

看到区别了吗,move constructor 是不需要 new 新对象的,只要将对应的字段也move一下,原有的字段设置成一个无效的值就行了,这样就保证了资源的安全,代码运行结果如下:

constructor A
move constructor A
>>>>num is nullptr
destructor A
flag 1
>>>>num value is 100
destructor A

这里面有很多的问题,我没有说完,比如如果不写move constructor, 程序会crash 吗?

相关文章

  • C++ 11 新特性(七)

    今天任性,想写一个自己感兴趣的问题,move 语义。 先上代码 问题是打印什么? 如果没有 move 语义,我想你...

  • C++ 11 语言特性介绍

    C++ 11 语言特性 新特性说明nullptr,autoNAfor-each区间迭代shared_ptr uni...

  • C++ 11常用特性

    C++ 11常用特性(转)

  • C++ 11 新特性

    C++11 中值得关注的几大变化(详解) | | 酷 壳 - CoolShell 1. delete 和 defa...

  • cppinsights 编译安装

    cppinsights 是一款C++源代码到源代码的转换,它可以把C++中的模板、auto以及C++11新特性展开...

  • C++ 11 新特性汇总

    内容引自《写给大忙人看的C++》,未包含多线程相关话题,但是基本上C++最重要的方面都包括在内了 概要 改进的对象...

  • C++ 11新特性(部分)

    1. 右值引用 对左值的引用(lValue),放在赋值表达式左边的,有精确的内存地址; 右值(rValue) 指的...

  • C++ 11 新特性(四)

    Lambda 表达式在一定程度上是可以和函数对象进行互转的。例子如下: 从代码中可以推测,Lambda 的捕获代码...

  • C++ 11 新特性(一)

    看下面代码,回答问题: 变量x的数据类型是什么? 其实我也不知道,这要是在C99中是不会这么使用的,但是代码的确可...

  • C++ 11 新特性(二)

    Lambda 表达式。在C99中因为没有这个东西,导致STL库中的if算法都不太方便使用,但是有了Lambda表达...

网友评论

      本文标题:C++ 11 新特性(七)

      本文链接:https://www.haomeiwen.com/subject/gsobgftx.html