【问题标题】:Iterate raw pointers from unique_ptr in map values从 map 值中的 unique_ptr 迭代原始指针
【发布时间】:2016-07-06 17:55:55
【问题描述】:

我在地图值中使用了 unique_ptr。我需要将这些值作为原始指针的列表/向量。到目前为止,我已经完成了以下工作。

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <map>

class Foo {
  public:
    std::string val;

    Foo(std::string v) : val(v) {
    }
 };

 class Unique {
   public:
     std::map<int, std::unique_ptr<Foo>> unique_map;

     std::vector<Foo*> getFoos() {
       std::vector<Foo*> foos;
       for (auto& it : unique_map) {
         foos.push_back(it.second.get());
       }

       return foos;
     }
 };

 int main() {
   Unique unique;
   Foo* f1 = new Foo("1");
   Foo* f2 = new Foo("2");

   unique.unique_map.emplace(1, f1);
   unique.unique_map.emplace(2, f2);

   std::vector<Foo*> foos = unique.getFoos();

   for (Foo* foo : foos) {
     std::cout << foo->val;
   }

   std::cout<<"\n";

   return 0;
 }

但这无法编译。最相关的错误信息似乎是

"/usr/include/c++/4.8/bits/stl_tree.h:140:49: 注意:无法转换 'std::forward((* & __args#1))'(输入'Foo*')来输入'const std::unique_ptr&'"

但我不确定我是否理解它的含义,因为我的理解是 it.second 返回一个对 unique_ptr 的引用,而不是它自己假设问题所在的 Foo 实例。需要做什么来修复这个例子?

编辑 我使用的是较旧的 g++ 版本。

g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

使用命令行。

g++ -std=c++11 -o unique unique.cpp

【问题讨论】:

  • 为我编译。 g++ (GCC) 6.1.1 20160602,没有额外的标志。
  • 有趣。所以它可能是一个编译器错误?刚刚添加了我的编译器详细信息。
  • Clang++ 也接受它(当给定 -std=c++11 时)。 clang version 3.8.0 (tags/RELEASE_380/final.
  • @chamibuddhika 它不是编译器错误。如果它编译,那么这是一个错误。
  • @Thomas 在您测试代码的版本中,unique_ptr 构造函数不是显式的。将原始指针隐式转换为 smart_pointer 是一项危险的业务

标签: c++ c++11 smart-pointers


【解决方案1】:

您得到的错误是因为 Foo*std::unique_ptr&lt;Foo&gt; 的隐式转换是不允许的。那是因为,unique_ptr 的构造函数采用原始指针标记为explicit

explicit
      unique_ptr(pointer __p) noexcept
      : _M_t(__p, deleter_type())
      { static_assert(!is_pointer<deleter_type>::value,
                     "constructed with null function pointer deleter"); }

因此,您应该在创建emplace 的同时创建unique_ptrmove

注意:我不确定它为什么或如何在 g++ > 6.0 库中工作。但我个人认为将原始指针隐式转换为智能指针并不安全。要了解原因,请参阅:https://stackoverflow.com/a/11367997/434233

【讨论】:

  • 感谢您的解释和链接。现在更有意义了。既然您解释了这种行为的原因,我将接受它作为更好的答案。
  • @Arunmu 完全同意这种隐式转换是危险的,但是您链接到的 Sutter 文章谈到了另一个方向(智能到原始,而不是原始到智能)。
  • @Thomas 是的,谢谢。更新了指向相关答案的链接
【解决方案2】:

当我运行这段代码时,投诉似乎与std::pair 类的创建有关。

unique.unique_map.emplace(1, std::unique_ptr<Foo>(f1));
unique.unique_map.emplace(2, std::unique_ptr<Foo>(f2));

对我来说,这是构建并且有效的,并不是说我可以肯定地说它真的会满足你的需求。只是它为我编译和运行。

我的大部分 C++ 时间都在使用 QT 库和类,但在我看来,它似乎无法找到将一对 FOO* 转换为 unique_ptr&lt;FOO&gt; 的方法。

【讨论】:

  • 确实!当我使用基于显式 std::pair 的插入时,它起作用了。看起来 emplace 不像我想的那样工作(至少对于我当前的编译器来说)。
猜你喜欢
  • 1970-01-01
  • 2015-05-02
  • 2014-10-25
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2021-03-18
  • 2012-04-12
  • 1970-01-01
相关资源
最近更新 更多