对象的数据成员的shared_ptr是否使数据成员保持活动超过对象的生命周期?

时间:2016-03-10 10:48:19

标签: c++ c++11 shared-ptr

我有以下代码框架。 pValue映射的生命周期之后values是否仍可访问?

class Value { /* ... */ };
enum Key { aKey /* , ... */ };

class ValueStorage
{
public:
    ValueStorage() { /* calculate all kinds of values and store them */ }

    // returns nullptr if not available
    std::shared_ptr<Value> getValue(Key key)
    {
        auto it = values.find(key);
        return it != values.end() ? shared_ptr<Value>(&it->second) : nullptr;
    }
private:
    std::map<Key, Value> values;
};

shared_ptr<Value> pValue;
{
    ValueStorage values;
    pValue = getValue(aKey);
}
assert (pValue.get()); // is the Value the shared_ptr refers to still alive ? 

如果不是,我怎么能避免这个问题?我可以改变一些getValue的实现吗?

或者,如果我无法避免这个问题,是否应该更好地返回一个裸指针以避免混淆其生命周期?

(我本可以通过返回值而不是指针来避免麻烦,但我更喜欢指针版本,因为它允许在值不可用时返回nullptr)

3 个答案:

答案 0 :(得分:4)

这将是一个问题,因为你根据从地图获取的元素的地址在std::shared_ptr<Value>中构建getValue(),当地图被破坏时,其所有元素也将被销毁,然后指针shared_ptr持有变得悬空。

new getValue()中的新指针shared_ptr delete最终会std::shared_ptr<Value> getValue(Key key) { auto it = values.find(key); return it != values.end() ? shared_ptr<Value>(new Value(it->second)) : nullptr; }

SELECT sessionname, left(comment,4)) 
  FROM moma_reporting.comments where name like '%_2016_02_%'
  and comment = '1200'

并且不返回裸指针,问题根本不会改变。

答案 1 :(得分:2)

另一种方法是在地图中存储shared_ptr

std::map<Key, shared_ptr<Value>> values;

通过这种方式,函数getValue将调用shared_ptr的复制构造函数,从而增加其计数器。

答案 2 :(得分:1)

能够返回一个不存在的&#34;句柄不是使用shared_ptr的好理由。正如评论中所建议的那样,使用optional,或者返回一个裸(可能为空)指针。

如果出于某种原因需要shared_ptr,您需要考虑所有权。

在这种情况下,所有Value都归std::map所有,ValueStorageValueStorage拥有。这意味着只要shared_ptr<Value>周围至少有一个ValueStorageshared_ptr就必须存在。

为了实现这一目标,您希望getValue生命周期由shared_ptr管理,shared_ptr将返回使用相同控制块的ValueStorage作为管理enable_shared_from_this的{​​{1}}。

您可以使用shared_ptr<T>shared_ptr( shared_ptr<U>, T* )的构造函数以及签名class ValueStorage : public std::enable_shared_from_this<ValueStorage> { public: ValueStorage() { /* calculate all kinds of values and store them */ } // returns nullptr if not available std::shared_ptr<Value> getValue(Key key) { auto it = values.find(key); if ( it == values.end() ) return nullptr; // Return a shared_ptr that uses the same control block of // this ValueStorage // Note: this works as long as you do not invalidate "it", // so you should not ever erase an element from the map. return shared_ptr<Value>(shared_from_this(), &it->second); } private: std::map<Key, Value> values; }; shared_ptr<Value> pValue; { // ValueStorage needs to be managed by a shared_ptr. auto values = std::make_shared<ValueStorage>(); // values can go out of scope // the ValueStorage will be kept alive as long as pValue is alive pValue = values->getValue(aKey); } 来完成此操作。

var query="var1=5&var2=stackoverflow&var3=blah";
var arr=query.split("&");
result={};
for(i=0;i<arr.length;i++) {
    k = arr[i].split('=');
    result[k[0]] = (k[1] || '');
}; 
console.log(result);