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

对唯一指针列表排序

  •  2
  • Zach  · 技术社区  · 7 年前

    以下代码将无法编译:

    bool ptrLess(unique_ptr<int> ptr1, unique_ptr<int> ptr2)
    {
       return *ptr1 < *ptr2;
    }
    
    int main()
    {
       unique_ptr<int> ptr1(new int(3));
       unique_ptr<int> ptr2(new int(2));
       unique_ptr<int> ptr3(new int(5));
       list<unique_ptr<int>> list;
    
       list.push_back(ptr1);
       list.push_back(ptr2);
       list.push_back(ptr3);
    
       list.sort(ptrLess);
    
       for (auto &element : list) {
          cout << *element;
       }
    
       return 0;
    }
    

    我想这是因为 unique_ptr 的复制构造函数已删除。我得到一个错误,比如:

    错误C2280: STD::UngQuyPtR & G:; STD::UngyQuiTPT&L.;STD::Debug Tele&Lt.G.T.&G.&G.;& &;&: 引用已删除的函数

    有没有什么方法可以把 唯一指针 可能使用移动构造函数?

    4 回复  |  直到 7 年前
        1
  •  5
  •   joe_chip    7 年前

    您应该使用const-ref-毕竟您不想修改这些指针:

    bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2)
    

    如果你的 list 模板是 std::list ,然后将参数作为r值引用传递将不起作用- list::sort 必须打电话 std::move 有效地重置你的指针。

    编辑

    至于其他代码: STD::列表 有一个简便的方法 emplace_back (和) emplace_front )它允许您在适当的位置构造和附加一个元素:

    your_list.emplace_back(new int(2));
    
        2
  •  1
  •   Michael Beer    7 年前

    试试这个:

    #include <memory>
    #include <list>
    #include <iostream>
    using namespace ::std;
    
    bool ptrLess(unique_ptr<int>& ptr1, unique_ptr<int>& ptr2)
    {
       return *ptr1 < *ptr2;
    }
    
    int main()
    {
       unique_ptr<int> ptr1(new int(3));
       unique_ptr<int> ptr2(new int(2));
       unique_ptr<int> ptr3(new int(5));
       list<unique_ptr<int>> list;
    
       list.push_back(move(ptr1));
       list.push_back(move(ptr2));
       list.push_back(move(ptr3));
    
       list.sort(ptrLess);
    
       for (auto &element : list) {
          cout << *element;
       }
    
       return 0;
    }
    

    这里的问题是你需要了解 unique_ptr 实际目标是:

    在处理指针/引用时,如果有多个指针/引用引用引用同一对象,则会出现很多潜在问题。 唯一指针 尽量避免这种情况。 因此,不能创建2 唯一指针 指同一对象。

    你不能用你的 ptrLess() 函数,因为像这样调用它

       unique_ptr<int> ptr1(new int(3));
       unique_ptr<int> ptr2(new int(2));
    
       ptrLess(ptr1, ptr2);
    

    因为这意味着 ptr1 ptr2 必须复制并转交给 无指针() -这里的关键字是“按值调用”。

    而且,你做不到

       list<unique_ptr<int>> list;
       unique_ptr<int> ptr1(new int(3));
    
       unique_ptr<int> ptr1(new int(3));
    

    因为这也需要创建 PTR1 . 这里的解决方案是不通过 唯一指针 S to ptrLess 作为值,但作为参考:

    bool ptrLess(unique_ptr<int>& ptr1, unique_ptr<int>& ptr2);
    

    你不会把副本传给名单,但是 移动 你的目标是:

    list.push_back(move(ptr1));
    

    这里的关键字是“移动语义”。 这将使您的 PTR1 变量-对象已移出 PTR1 在列表中。

    如果您对这类事情更感兴趣,我建议您看看Rust语言;)

    正如鲍姆米特奥根指出的,参数 无指针 最好声明为 const :

    bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2);
    
        3
  •  -1
  •   Ian4264    7 年前

    尝试通过const-ref传递,这样它就不会复制参数: bool ptrless(const unique&ptr&ptr1,const unique&ptr&ptr2)返回*ptr1<*ptr2;

        4
  •  -1
  •   catnip    7 年前

    我突然想到,如果操作系统使用 shared_ptr 而不是 unique_ptr 那么最初发布的代码将以其他方式不变运行:

    #include <memory>
    #include <list>
    #include <iostream>
    using namespace ::std;
    
    bool ptrLess(const shared_ptr<int>& ptr1, const shared_ptr<int>&  ptr2)
    {
       return *ptr1 < *ptr2;
    }
    
    int main()
    {
       shared_ptr<int> ptr1(new int(3));
       shared_ptr<int> ptr2(new int(2));
       shared_ptr<int> ptr3(new int(5));
       list<const shared_ptr<int>> list;
    
       list.push_back(ptr1);
       list.push_back(ptr2);
       list.push_back(ptr3);
    
       list.sort(ptrLess);
    
       for (auto &element : list) {
          cout << *element;
       }
    
       return 0;
    }
    

    运行它 Wandbox .

    从某种意义上说,这是一种始终如一的做事方式。 push_back 通常会将要添加到列表中的对象复制到列表中,如果调用者想要使用原始对象,则保持原始对象对调用者可用。使用 共享资源 具有相似的语义,而不需要复制对象本身的开销。相反,只是 共享资源 是复制的,这是一个便宜的操作。

    另外,将操作的原始代码修改为 move 这个 unique_ptrs 列入名单本身就很脆弱。它们保留在调用方的作用域内,但不再可用。你会得到一个 nullptr 如果你尝试的话就取消引用。更好的方法是,这样做(注意额外的一组大括号):

    ...
    
    list<unique_ptr<int>> list;
    
    {
       unique_ptr<int> ptr1(new int(3));
       unique_ptr<int> ptr2(new int(2));
       unique_ptr<int> ptr3(new int(5));
    
       list.push_back(move(ptr1));
       list.push_back(move(ptr2));
       list.push_back(move(ptr3));
    }
    
    ...
    

    现在你安全了。

    在这里,这是一个比原始版本更好的帖子,抱歉。

    推荐文章