C++ primer
显示了一个示例:
auto &nos = result[word];
if (!nos) nos.reset(new std::set<int>);
结果为std::map<string, shared_ptr<std::set<int>>>
。
我的问题是:如果!nos
成立,nos
是否为空?那为什么我们可以在此reset
上调用shared_ptr
方法?
答案 0 :(得分:4)
是的,它是空的,在中它没有指向任何数据意义,但它仍然是有效的shared_ptr
对象。在示例代码中,您使用有效指针重新设置它。
或者,你可以这样写:
auto &nos = result[word];
if (!nos) nos = std::make_shared<std::set<int>>();
答案 1 :(得分:2)
任何智能指针都是原始指针的包装器。如果你让事情变得非常简单,那么智能指针可能看起来像这样:
template< class T >
class some_smart_ptr
{
public:
<...>
void reset(T * ptr)
{
delete _data; // possibly
_data = ptr;
}
operator bool()
{
return _data == nullptr;
}
T * operator->()
{
return _data;
}
<...>
private:
T * _data = nullptr;
};
正如您所看到的,它有一个指向数据的内部原始指针,以及用于访问数据的重载operator->
。 reset函数获取它作为参数获取的指针的所有权,可能删除先前存储在_data
的对象(例如,当没有其他共享指针指向同一{{1}时,它发生的共享指针}})。
如果也有重载_data
,那么可以在条件中使用它。在这种情况下,它只检查智能指针是否指向任何有意义的东西。如您所见,operator bool
为null并不会阻止您使用智能指针本身。
_data
答案 2 :(得分:1)
基本上 shared_ptr 有operator bool overload。
所以这是检查 shared_ptr 是否存储非空指针。
答案 3 :(得分:0)
在此代码中:
auto &nos = result[word];
if (!nos) nos.reset(new std::set<int>);
nos
的类型为std::shared_ptr<std::set<int>>&
,因此nos
不为空,实际上不能为空。
if (!nos)
会致电if (!nos.operator bool())
(请参阅std::shared_ptr::operator bool
),这会检查nos
是否持有nullptr
。如果它保持nullptr
,则将其重置为有效指针。
注意,您可以看到nos.reset(new std::set<int>);
是member-of-object
运算符,而不是member-of-pointer
运算符。请参阅Member access operators
在std::shared_ptr
中,member-of-pointer
运算符被这个实现所覆盖:
T * operator->()
{
return /* the raw pointer */;
}
答案 4 :(得分:0)
鉴于
result = std::map<std::string, std::shared_ptr<std::set<int>>>;
然后operator[]()
在这一行:
auto &nos = result[word];
给我们提及
result
包含word
)对现有共享指针的引用,或result
不包含word
)新的默认构造的共享指针。在第二种情况下,默认构造的共享指针不管理任何对象,其operator bool()
返回false。这可以称为空智能指针。在这种情况下,下一行将其设置为指向新构造的集合,以便具有相同参数的后续operator[]()
将返回非空指针:
if (!nos)
nos.reset(new std::set<int>);
reset()
方法的操作是:
shared_ptr
,那么将其删除。 (我们从if (!nos)
知道这个指针尚未拥有一个对象,所以在这一步中没有任何反应。)std::set
。当它的最后一个共享指针被销毁时,将使用delete
销毁它。)关于此代码的几点说明:
result
简化为std::map<std::string, std::set<int>>
。std::make_shared()
创建一个共享指针的数据位置更差,因为没有机会组合对象的分配和指针的控制结构