总在需要的时候使用 noexcept

Posted by w@hidva.com on March 23, 2016
  • 总是在需要的时候使用noexcept(true)来标识你的函数.这样可能会提升性能!

    • 不使用noexcept(true)来标识函数

      #include <stdio.h>
      #include <vector>
      
      struct X {
          X() = default;
      
          X(const X &arg)
          {
              printf("func: %s;this: %p;arg: %p\n",__PRETTY_FUNCTION__,this,&arg);
              return ;
          }
      
          X(X &&arg)
          {
              printf("func: %s;this: %p;arg: %p\n",__PRETTY_FUNCTION__,this,&arg);
              return ;
          }
      };
      
      int
      main(int argc,char **argv)
      {
          std::vector<X> x_vector;
          for (int i = 0; i < 3; ++i) {
              X x;
              printf("x: %p\n",&x);
              x_vector.push_back(std::move(x));
          }
          return 0;
      }
      
      x: 0x7ffd890bf92b
      func: X::X(X&&);this: 0xb84010;arg: 0x7ffd890bf92b
      x: 0x7ffd890bf92b
      # 这里需要分配额外的空间来存放新插入的元素.即分配新空间,然后把原来空间中的对象移到新空间.
      # 按理说,这里应该调用 X(X&&) 的,而且这样性能更改,但由于 X(X&&) 可能会抛出异常.所以
      # 此处调用 X(const X&).
      # Q1: 其实按照我的理解,这里 X(const X&) 也可能会抛出异常,既然都会抛出异常,不如调用 X(X&&)
      #   好了,但是 vector 还是调用复制构造函数.
      func: X::X(X&&);this: 0xb84031;arg: 0x7ffd890bf92b
      func: X::X(const X&);this: 0xb84030;arg: 0xb84010
      x: 0x7ffd890bf92b
      # 同上
      func: X::X(X&&);this: 0xb84012;arg: 0x7ffd890bf92b
      func: X::X(const X&);this: 0xb84010;arg: 0xb84030
      func: X::X(const X&);this: 0xb84011;arg: 0xb84031
      
    • 使用noexcept(true)来标识函数

      --- move_vector_test_noexcept_false.cc  2016-03-23 18:04:37.902618117 +0800
      +++ move_vector_test_noexcept_true.cc   2016-03-23 18:04:54.726802880 +0800
      @@ -11,7 +11,7 @@
              return ;
          }
      
      -    X(X &&arg)
      +    X(X &&arg) noexcept(true)
          {
              printf("func: %s;this: %p;arg: %p\n",__PRETTY_FUNCTION__,this,&arg);
              return ;
      
      x: 0x7ffd418fd8fb
      func: X::X(X&&);this: 0x1d1d010;arg: 0x7ffd418fd8fb
      x: 0x7ffd418fd8fb
      # 与上面移动构造函数可能会抛出异常时相比,这里指定了在移动构造函数中异常不会抛出!所以在将
      # 旧空间中对象移动到新空间时,直接调用移动构造函数!
      func: X::X(X&&);this: 0x1d1d031;arg: 0x7ffd418fd8fb
      func: X::X(X&&);this: 0x1d1d030;arg: 0x1d1d010
      x: 0x7ffd418fd8fb
      func: X::X(X&&);this: 0x1d1d012;arg: 0x7ffd418fd8fb
      func: X::X(X&&);this: 0x1d1d010;arg: 0x1d1d030
      func: X::X(X&&);this: 0x1d1d011;arg: 0x1d1d031
      

转载请注明出处!谢谢