作为类成员的两个类之间的共享指针

Shared pointer between two classes as class member

本文关键字:之间 两个 共享 指针 成员      更新时间:2023-10-16

我有以下类结构:

class Bar {
private:
    std::shared_ptr<std::vector<int>> y_;
public:
    Bar(std::shared_ptr<std::vector<int>> p):
        y_(p)
    {}
    int getFirstVal() {return y_->at(0);};
};
class Initialiser {
private:
    std::vector<int> x_;
    Bar bar_;
public:
    Initialiser(std::vector<int>& v):
        x_(v),
        bar_(std::make_shared<std::vector<int>>(x_))
    {}
    void set_x(std::vector<int> x) {x_ = x;}
    void check(std::vector<int> x){
        set_x(x);
        std::cout << "New value of x= " << bar_.getFirstVal() << std::endl;
    }
};

int main(){
    std::vector<int> z = {1,2,3};
    Initialiser init(z);
    std::vector<int> x_new = {4,5,6};
    init.check(x_new); // should print 4

}

在班级初始评估器中,我作为私人成员一个INT的向量和类栏的实例。应用与INT的向量的共享指针初始化栏,该向量应在初始化器和栏之间共享。但是,如果启动器调用X的设置器,则不会影响bar内部的向量。我在 check((中演示了这一点。为什么不 check((打印值4,但仍然值1?

Initialiser(std::vector<int>& v):
    x_(v),
    bar_(std::make_shared<std::vector<int>>(x_))
{}

您创建一个共享_ptr,指向一个新的向量,即x_的 copy 。自然,修改一个不会影响另一个。

直接方向的解决方案是让启动器和bar保留向量的共享_ptr:

class Initialiser {
private:
    std::shared_ptr<std::vector<int>>  x_;
    Bar bar_;
public:
    Initialiser(std::vector<int>& v):
        x_(std::make_shared<std::vector<int>>(v)),
        bar_(x_)
    {}
};

但是,由于bar对象是启动器对象的一部分,因此实际上根本不需要智能指针。条可以简单地将其引用。这里没有终身管理问题,因为BAR_永远不会超过其容器,也不会超过容器bar_。

class Bar {
private:
    std::vector<int>& y_;
public:
    Bar(std::vector<int>& p):
        y_(p)
    {}
    int getFirstVal() {return y_.at(0);};
};
class Initialiser {
private:
    std::vector<int>  x_;
    Bar bar_;
public:
    Initialiser(std::vector<int>& v):
        x_(v),
        bar_(x_)
    {}
};

但是,请注意,x_和bar_的顺序很重要,因此使它有点脆弱。成员变量的构建顺序是它们在类定义中出现的顺序,而不是成员初始化列表中的顺序。如果订单颠倒了,则该程序的行为将不确定,因为BAR_将在x_。

之前构造

此正确的排序还确保X_在对象破坏过程中不会超过bar_,因为成员以相反顺序销毁其初始化。