代码之家  ›  专栏  ›  技术社区  ›  Neil G

C++ 0X UnQuyjpTR取代StimeDePPTR取得所有权?

  •  19
  • Neil G  · 技术社区  · 15 年前

    我以前写过这样的代码:

    class P {};
    
    class Q: public P {};
    
    class A {
        // takes ownership
        A(P* p): p_(p) {}
    
        scoped_ptr<P> p_;
    };
    
    A a(new Q);
    

    class A {
        // takes ownership
        A(unique_ptr<P>&& p): p_(p) {}
    
        unique_ptr<P> p_;
    };
    
    5 回复  |  直到 14 年前
        1
  •  43
  •   Howard Hinnant    14 年前

    我对科莫纳德的回答投了赞成票,但有一个警告:

    不允许 作用域指针 常量唯一\u ptr .

    const std::unique_ptr 不如 boost::scoped_ptr

    编辑:

    下面是 boost::作用域\u ptr 我认为应该失败,但事实并非如此。它确实失败了 std::unique_ptr :

    #include <iostream>
    
    #ifdef USE_UNIQUEPTR
    
    #include <memory>
    typedef std::unique_ptr<int> P;
    
    #else  // USE_UNIQUEPTR
    
    #include <boost/scoped_ptr.hpp>
    typedef boost::scoped_ptr<int> P;
    
    #endif  // USE_UNIQUEPTR
    
    int main()
    {
        P p1(new int(1));
        {
            // new scope
    #ifdef USE_UNIQUEPTR
            const P p2(new int(2));
    #else  // USE_UNIQUEPTR
            P p2(new int(2));
    #endif  // USE_UNIQUEPTR
            swap(p1, p2);  // should fail!
        }
        std::cout << *p1 << '\n';
    }
    

    如果 如果它的资源不会脱离当前的范围,那么它就不如一个企业那样善于把握这一承诺 常量标准::唯一\u ptr . 如果我们想比较const::boost::scoped \u ptr和const::std::unique \u ptr,我必须问:为什么?它们在我看来是一样的,只是const std::unique \-ptr允许定制的构造和销毁。

        2
  •  30
  •   Community CDub    8 年前
    • A 是指针 具有 复制 移动 语义和所有权(=自动删除)。
    • A 唯一\u ptr 自动\u ptr 无副本 但是 具有 语义学。
    • A 作用域指针 自动\u ptr 不动 语义学。

      错误的选择 这是显而易见的。

      无论何时你想明确地 移动语义,使用 .

      无论何时你想明确地 不允许 移动语义,使用 .

    • 互换 语义学,比如 p.swap(q) . 要禁止这些,请使用

    有些情况下,你想使用 作用域指针 指向几个可互换对象中的一个:由于缺少移动语义,它不会因为意外的移动而意外地指向null是非常安全的(对于明显的bug)。值得一提的是: 作用域指针 s还是可以的 互换 高效的ped。要使其可移动和/或可复制,但仍然使用这些交换语义,您可能需要考虑使用 指向一个 作用域指针

    看到了吗 stackoverflow:smart-pointers-boost-explained

        3
  •  2
  •   Khaled Alshaya    15 年前

    在我看来,使用 unique_ptr 移动语义 . i、 你可以为你的类编写一个move构造函数等,不像 scoped_ptr . 也, 唯一\u ptr 作用域指针 ,因此是一个优越的设施。当然,重写的决定取决于您,如果您不需要移动语义,那么重写就没有意义了。别忘了 唯一\u ptr

        4
  •  2
  •   James Michael Hare    15 年前

    我不同意阿拉克的观点。在两者之间没有一个更好的选择,因为它通常取决于用法。这就好比说智能汽车在所有用途上都优于皮卡车,因为它更轻更快。实际上,有时你需要一辆卡车,有时你不需要。指针的选择应该基于您的需要。

    scoped\u ptr的优点是增加了安全级别。通过使用scoped\u ptr,您会注意到所创建的内存将只存在于该作用域,而不再存在,因此您可以获得编译时保护,以防试图移动或传输它。

    所以,如果你想创建一些东西,但是限制它的作用域,可以使用scoped\u ptr。如果你想创建一些东西并且所有权可以移动,请使用unique\ ptr。如果您想创建一些东西,并在所有引用都不存在时共享指针和清理,请使用shared\u ptr。

        5
  •  1
  •   Dan    13 年前

    move(p) 在初始化器内部。 std::move 将给定的任何内容视为右值引用,在您的情况下,即使您的参数是对某个对象的右值引用,也将其传递给其他对象(例如 p_ 的构造函数)将传递左值引用,默认情况下不会传递右值引用。

    根据Karu的评论,还添加了必要的内容,使我的代码可编译。

    #include <memory>
    #include <cassert>
    #include <vector>
    using namespace std;
    
    class A {};
    
    class B {
    public:
      void takeOwnershipOf(unique_ptr<A>&& rhs) {
        // We need to explicitly cast rhs to an rvalue when passing it to push_back
        // (otherwise it would be passed as an lvalue by default, no matter what
        // qualifier it has in the argument list).  When we do that, the move
        // constructor of unique_ptr will take ownership of the pointed-to value
        // inside rhs, thus making rhs point to nothing.
        owned_objects.push_back(std::move(rhs));
      }
    
    private:
      vector<unique_ptr<A>> owned_objects;
    };
    
    int main() {
      unique_ptr<B> b(new B());
      // we don't need to use std::move here, because the argument is an rvalue,
      // so it will automatically be transformed into an rvalue reference.
      b->takeOwnershipOf( unique_ptr<A>(new A()) );
    
      unique_ptr<A> a (new A());
      // a points to something
      assert(a);
      // however, here a is an lvalue (it can be assigned to). Thus we must use
      // std::move to convert a into an rvalue reference.
      b->takeOwnershipOf( std::move(a) );
      // whatever a pointed to has now been moved; a doesn't own it anymore, so
      // a points to 0.
      assert(!a);
      return 0;
    }
    

    另外,在最初的示例中,您应该重写类A,如下所示:

    A级{ //取得所有权 A(唯一)

    &&p) :p(std::move(p)){}

    unique_ptr<P> p_;
    

    };

    推荐文章