为啥我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy?

Posted

技术标签:

【中文标题】为啥我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy?【英文标题】:Why can't I perform a std::copy on a vector of std::shared_ptr's in C++0x?为什么我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy? 【发布时间】:2011-07-12 07:26:10 【问题描述】:

我在我的程序中编写了一个路径类来处理层次路径结构。我决定使用 std::shared_ptr 作为整个类的标准返回类型,因为我越来越喜欢它了。

令我惊讶的是,我无法使用 std::copy 或正常的 vector.insert(v.begin(), v.end()) 将元素复制到 shared_ptr 的向量或从这些向量复制。这是为什么呢?

shared_ptr<vector<shared_ptr<bfile>>> butils::bfile::search()

    shared_ptr<vector<shared_ptr<bfile>>> ret(new vector<shared_ptr<bfile>>());
    shared_ptr<vector<shared_ptr<bfile>>> children = getChildren();

    //WTF why don't either of these work?
    //std::copy(children->begin(), children->end(), back_inserter(ret));
    //ret->insert(children->begin(), children->end());

    //I've had to resort to doing this....
    for (auto c = children->begin(); c != children->end(); c++)
    
        ret->push_back(*c);
        auto cChildren = (*c)->search();
        for (auto cc = cChildren->begin(); cc != cChildren->end(); cc ++)
        
            ret->push_back(*cc);
        
    

    return ret;

当我尝试 std::copy() 时,我得到了:

1>C:\Program Files (x86)\Microsoft 视觉工作室 10.0\VC\include\iterator(21): 错误 C2039: 'const_reference' : 不是 'std::tr1::shared_ptr<_ty>' 的成员 1> 与 1> [ 1> _Ty=std::vector> 1> ] 1> BFile.cpp(329):见参考 类模板实例化 'std::back_insert_iterator<_container>' 正在编译 1> 与 1> [ 1> _Container=std::tr1::shared_ptr>> 1>]

当我尝试 insert(v.begin(), v.end()) 时,我得到了;

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(208): error C2664: 'std::tr1::shared_ptr<_Ty>::shared_ptr(std::nullptr_t)' : cannot convert parameter 1 from 'std::_Vector_iterator<_Myvec>' to 'std::nullptr_t'
1>          with
1>          [
1>              _Ty=butils::bfile
1>          ]
1>          and
1>          [
1>              _Myvec=std::_Vector_val<std::tr1::shared_ptr<butils::bfile>,std::allocator<std::tr1::shared_ptr<butils::bfile>>>
1>          ]

我不确定我是否理解这些编译器错误...还有其他人有线索吗?

【问题讨论】:

不要太喜欢shared_ptr,只要没有“共享”所有权,就更喜欢使用unique_ptr。共享所有权是它自己的一个概念,不应该为了ease而被滥用,因为它有自己的问题(引用循环),只能由内存泄漏工具检测到......经验丰富的程序员 @Matthieu - 我同意你的观点,尽管考虑到这里的对象只是带有字符串和一些状态的路径对象,很难看出它们如何导致引用循环. 【参考方案1】:

您正在尝试将back_inserter 指向指向向量的指针,而不是向量本身。将back_inserter(ret) 更改为back_inserter(*ret)(如果你真的觉得需要动态分配这样的向量)。

insert 失败,因为您缺少参数:

ret->insert(ret->begin(), children->begin(), children->end());

出现奇怪的错误消息是因为insert 的两个参数重载,第二个参数是要插入的对象。编译器尝试使用它,但无法将迭代器转换为对象类型。

【讨论】:

【参考方案2】:

std::back_inserter 需要一个序列,而不是 std::shared_ptr。使用back_inserter(*ret)

对于第二个,insert() 这里需要第三个参数:insert(where_to_insert,start,end)

【讨论】:

insert(0,start,end) 似乎不起作用,但我认为您的想法是正确的:我猜您的意思是:ret->insert(ret->begin(), children- >开始(),孩子->结束());确实有效,谢谢! 是的 - 抱歉,很快忘记了我们在谈论迭代器,而不是索引。已编辑。 是的,我认为他的意思是ret-&gt;begin()。在此处查看参考:cplusplus.com/reference/stl/vector/insert【参考方案3】:

考虑使用 std::transform 代替 std::copy。

std::transform(children->begin(), 
               children->end(), 
               back_inserter(ret),
               [](const bfile& in)  return make_shared<bfile>(in); );

【讨论】:

以上是关于为啥我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy?的主要内容,如果未能解决你的问题,请参考以下文章

关于24c02芯片的程序问题,希望得到帮助解决,下面的程序有啥问题,为啥下载到单片机里面不能运行!

为啥我不能使用'0x80000000'来初始化一个int数组?

为啥在逻辑回归中对 roc_auc 进行评分时,GridSearchCV 不给出具有最高 AUC 的 C

如果我包含“-ansi”编译器选项,为啥我的 C++0x 代码无法编译?

为啥 C++0x 中有 sizeof... 运算符?

为啥类不能从 decltype 的结果继承?