我有以下代码框架。 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)
答案 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
所有,ValueStorage
由ValueStorage
拥有。这意味着只要shared_ptr<Value>
周围至少有一个ValueStorage
,shared_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);