2017-04-26 83 views
0

我有下面的類結構:共用指針作爲類成員

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 



} 

在類初始化劑,我具有如私有成員整數的向量和的類BAR的一個實例。條應該用一個指向int整數的共享指針進行初始化,並且這個向量應該在Initializers和Bar之間共享。然而,目前,如果Initialiser調用x的setter,這不會影響bar內的向量。我在檢查()中證明了這一點。爲什麼check()打印值爲4但仍爲值1?

回答

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

您創建一個shared_ptr,它指向一個新的載體,即X_的副本。當然,修改一個不會影響另一個。

直進的解決方案是有兩個初始化器和酒吧舉行一個shared_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_,因爲成員以與其初始化相反的順序銷燬。

+0

另外值得指出的是,在這種情況下,不需要'shared_ptr',它可能適用於'Bar'對象持有一個指針或對'Initialiser'擁有的向量的引用。 – Persixty

+1

@丹艾倫 - 是的,我只是在添加這個過程。謝謝:) – StoryTeller

+0

感謝您的幫助!這是一個很好的解決方案。 – beginneR