shared_ptrs 的向量,从函数返回并修改它

Posted

技术标签:

【中文标题】shared_ptrs 的向量,从函数返回并修改它【英文标题】:vector of shared_ptrs, returning it from a function and modifying it 【发布时间】:2013-03-01 21:27:53 【问题描述】:

基本上,我希望我的 2 个类共享一些数据,我希望将这些数据作为 shared_ptr 对象的向量。

我已将我的代码缩减为以下简单的可编译示例。

我希望对象 A 查看在对象 B 中初始化的数据。但是,当我尝试在 A 的方法中执行 push_back() 时,它并没有改变 B 中 shared_ptr 对象向量的大小。 (在注释“这是兴趣点”的那一行。)

我需要使用什么方法来获得此功能,还是我走错了路。 (这里是 c++ 新手)

#include <memory>
#include <vector>
#include <iostream>
using std::cout;
using std::endl;
class DataClass 
    public:
        int i_;
;
class B 
    public:
        // constructor:
        B() : my_data_(std::vector<std::shared_ptr<DataClass> >()) 
            my_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            my_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            my_data_[0]->i_ = 1;
            my_data_[1]->i_ = 2;
            cout<<my_data_.size()<<endl;
        ;

        // return the data
        std::vector< std::shared_ptr<DataClass> > get_my_data() 
            return my_data_;
        ;

        // check the data:
        void CheckData() 
            cout<<my_data_.size()<<endl; // This is the point of interest
        ;
        // member variable
        std::vector< std::shared_ptr<DataClass> > my_data_;
;
class A 

    public:
        void start() 
            // begin interaction with B class:
            B b;

            // get the vector of data pointers:
            a_has_data_ = b.get_my_data();

            // modify some of the data:
            a_has_data_.push_back(std::shared_ptr<DataClass> (new DataClass));
            a_has_data_[2]->i_ = 42;

            b.CheckData(); 
        ;
    private:
    std::vector< std::shared_ptr<DataClass> > a_has_data_;

;
int main() 
    A a;
    a.start();

【问题讨论】:

您正在制作矢量的副本。而是通过引用返回它:std::vector&lt; std::shared_ptr&lt;DataClass&gt; &gt;&amp; get_my_data() @Peter 这似乎不起作用,我认为这是因为我试图将引用保存为 A 中的成员变量?如果我这样做,它确实有效:b.get_my_data().push_back()...等,但是即使在你的建议之后,它也不能以如下形式工作:a_has_data_.push_back()。 您可能需要重新考虑您的设计。也许将这两个类结合起来,或者让数据存在于A 上。 【参考方案1】:

您正在返回向量的副本。您需要返回对数据的引用:

// return the data
std::vector< std::shared_ptr<DataClass> >& get_my_data()

        return my_data_;
;

那是A 正在访问b 的向量,而不是它的副本。

【讨论】:

这似乎不起作用,我认为是因为我试图将引用保存为A中的成员变量?如果我这样做,它确实有效:b.get_my_data().push_back()...等,但是即使在你的建议之后,它也不能以如下形式工作:a_has_data_.push_back()。 @CptLightning 那么您可以保留B 作为A 的数据成员,并删除矢量数据成员。问题是您试图将两个具有不同生命周期的东西耦合起来:B 位于 A::start() 的范围内,A::a_has_data 哦,是的,我现在确实看到了生命周期的冲突。谢谢【参考方案2】:
a_has_data_.push_back(std::shared_ptr<DataClass> (new DataClass));

由于返回类型是复制,上面的语句将修改a_has_data_。而在b.CheckData(); 中,您实际上是在检查b's 成员的大小。

A 中引入一个成员函数来检查向量大小,您应该会看到增加。

【讨论】:

【参考方案3】:

这里

 std::vector< std::shared_ptr<DataClass> > get_my_data()

值是通过值返回获得的,因此创建了新对象。请参阅以下实现。它通过发送指针来解决您的问题。

#include <tr1/memory>
#include <vector>
#include <iostream>
using namespace std;
using std::cout;
using std::endl;
class DataClass 
    public:
        int i_;
;
class B 
    public:
        // constructor:
        B() : my_data_(std::vector<tr1::shared_ptr<DataClass> >()) 
            my_data_.push_back(tr1::shared_ptr<DataClass> (new DataClass));
            my_data_.push_back(tr1::shared_ptr<DataClass> (new DataClass));
            my_data_[0]->i_ = 1;
            my_data_[1]->i_ = 2;
        ;

        // return the data
        std::vector< tr1::shared_ptr<DataClass> >* get_my_data() 
            return &my_data_;
        ;

        // check the data:
        void CheckData() 
            cout<<my_data_.size()<<endl; // This is the point of interest
        ;
        // member variable
        std::vector< tr1::shared_ptr<DataClass> > my_data_;
;
class A 

    public:
        void start() 
            // begin interaction with B class:
            B b;

            // get the vector of data pointers:
            a_has_data_ = b.get_my_data();

            // modify some of the data:
            b.CheckData(); 
            a_has_data_->push_back(tr1::shared_ptr<DataClass> (new DataClass));
            (*a_has_data_)[2]->i_ = 42;
            b.CheckData(); 
        ;
    private:
    std::vector< tr1::shared_ptr<DataClass> >* a_has_data_;

;
int main() 
    A a;
    a.start();

注意:我将代码更改为 tr1/memory,因为我使用的是旧版 gcc。

【讨论】:

在退出A::start() 作用域时,A::a_has_data_ 保留为悬空指针。 你需要为它写一个析构函数。我认为如果它的指针是隐含的:) 析构函数与它无关。 `A::a_has_data 析构函数不能解决问题。这是无关的。 是的,我想改变设计是更好的方法。 是的,我认为这是唯一的方法。

以上是关于shared_ptrs 的向量,从函数返回并修改它的主要内容,如果未能解决你的问题,请参考以下文章

存储 std::shared_ptr<Foo> 的向量,其中 Foo 是模板类

无法从 pybind11 中的静态函数返回 shared_ptr

python嵌入C++,函数返回shared_ptr(pybind11/boost_python)

如何将 shared_ptr 变量推回 C++ 中的 shared_ptr 向量?

用于将 shared_ptr 向量填充到基础和派生对象的函数模板

如何从类外修改向量