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

C++ 11 新特性(八)

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

在第六篇文章中我说有个问题,其实就是变量的生存周期问题,看如下代码:

#include <iostream>
#include <functional>

template<typename T>
class add {
   public:
      auto operator()(T n, T m) {
         std::cout << "n = " << n << std::endl;
         std::cout << "m = " << m << std::endl;
         return n + m;
      }
};

auto func(int n) {
   return std::bind(add<int>(), n, std::placeholders::_1);
}

int main() {
   auto f = func(5);
   std::cout << f(10) << std::endl;
   std::cout << f(200) << std::endl;
   return 0;
}

我在使用 std::bind 的时候内部申请了一个临时的对象 add<int>(),我的问题是为什么这个对象在函数func return以后没有被回收掉?这个违背了我对栈空间的理解了。我不清楚是编译器坐了优化了,还是C++特有的这个特性?

昨天测试了一段代码,也有类似的问题:


#include <iostream>

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

A func () {
   A a;

   return a;
}

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

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

   return 0;
}

这段代码的输出是什么?我想象中的结果应该会有一次构造函数调用,两次析构函数的调用。然后我又调整了代码如下:

#include <iostream>

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

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

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

A func() {
   A a;

   return a;
}

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

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

   return 0;
}

这次至少也要输出一个 拷贝构造函数啊,但是也没有,两次代码的输出结果如下:

constructor A
flag 1
destructor A

对于这样的输出我迷惑了,我想是不是我以前的理解都是错的?我不信我又修改了一下:

#include <iostream>

class A {
   public:
      A() {
         std::cout << "constructor A" << std::endl;
         n = nullptr;
      }

      A(const A &other) {
         std::cout << "copy constructor A" << std::endl;
         n = new int(100);

      }

      ~A() {
         if (n == nullptr) {
            std::cout << "n is nullptr" << std::endl;
         } else {
            std::cout << "n is %d" << *n << std::endl;
            delete n;
         }
         std::cout << "destructor A" << std::endl;
      }

   private:
      int * n;
};

A func() {
   A a;

   return a;
}

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

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

   return 0;
}

结果就是个悲剧,结果如下:

constructor A
flag 1
n is nullptr
destructor A

我做了最后一次尝试,代码如下:

#include <iostream>

class A {
   public:
      A() {
         std::cout << "constructor A" << std::endl;
         n = nullptr;
      }

      A(A &other) {
         std::cout << "copy constructor A" << std::endl;
         n = new int(100);

      }

      ~A() {
         if (n == nullptr) {
            std::cout << "n is nullptr" << std::endl;
         } else {
            std::cout << "n is %d" << *n << std::endl;
            delete n;
         }
         std::cout << "destructor A" << std::endl;
      }

   private:
      int * n;
};

A func() {
   A a;

   return a;
}

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

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

   return 0;
}

哈哈,编译不过!!!从这里我明白了一点东西了,编译器的确做了一些优化,不过这种优化更改了原有的语义,就像我们之前演示的那样,总是不能得到想要的结果!这个吗,我觉得无可厚非,为了追求性能,这么也不过分。

相关文章

  • C++ 11 新特性(八)

    在第六篇文章中我说有个问题,其实就是变量的生存周期问题,看如下代码: 我在使用 std::bind 的时候内部申请...

  • 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/prwggftx.html