代码之家  ›  专栏  ›  技术社区  ›  Bruce

已删除构造函数的RVO

  •  2
  • Bruce  · 技术社区  · 4 月前
    class Foo {
     public:
      Foo(const Foo&) = delete;
      Foo& operator=(const Foo&) = delete;
      Foo() = delete;
    };
    
    std::unique_ptr<Foo> CreateFoo() {
      return std::unique_ptr<Foo>();
    }
    
    int main(int argc, char** argv) {
      std::unique_ptr<Foo> result = CreateFoo();
      return 0;
    }
    

    Foo是不可移动构造的,因为复制构造函数/赋值运算符被删除了。我也删除了默认构造函数。

    代码运行良好 result is nullptr 在main的末尾。我可以看到RVO在这里是适用的,所以不需要复制/移动构造函数,但我也删除了默认构造函数。发生什么事?

    2 回复  |  直到 4 月前
        1
  •  6
  •   Remy Lebeau    4 月前

    默认构造 unique_ptr<T> 包含null T* 指针。它不会构建一个新的 T 对象。

    所以,你的 Foo 构造函数正在被调用。 CreateFoo() 正在返回a unique_ptr 持有null Foo* 指针。所以 result 也初始化为null。

    你编码了吗 CreateFoo() 拨打电话 std::make_unique<Foo>() 相反,那将是另一回事。然后,在尝试调用已删除的命令时,会出现编译器错误 Foo 建设者。

        2
  •  5
  •   NathanOliver    4 月前

    你的代码基本上什么都不做,这就是为什么它没有任何错误。

    std::unique_ptr<Foo> CreateFoo() {
      return std::unique_ptr<Foo>();
    }
    

    返回一个空值 unique_ptr ,你实际上并没有分配 Foo 它指向的对象。这与做基本相同 return foo*{} 如果你使用的是原始指针。

    int main(int argc, char** argv) {
      std::unique_ptr<Foo> result = CreateFoo();
      return 0;
    }
    

    在这里,您所要做的就是获取由返回的空指针的副本 CreateFoo() ,这不是问题。这就像做 foo* result = {};


    更改 CreateFoo

    std::unique_ptr<Foo> CreateFoo() {
      return std::make_unique<Foo>();
    }
    

    然后你会得到无法构建底层的错误 Foo 对象。


    最后要注意的是 unique_ptr 对于无法移动或复制的类型来说,这是一个完美的用例。对象在动态存储中创建,并始终保持在同一位置。它只是你移动的指针(手柄)。

    推荐文章