我对Cpp核心指南中的示例有疑问。在R.37: Do not pass a pointer or reference obtained from an aliased smart pointer中,有以下示例:
// global (static or heap), or aliased local ...
shared_ptr<widget> g_p = ...;
void f(widget& w)
{
g();
use(w); // A
}
void g()
{
g_p = ...; // oops, if this was the last shared_ptr to that widget, destroys the widget
}
我不明白第一条评论中“ aliased local”的含义。它是否连接到别名指针类型,如
using WidgetPtr = std::shared_ptr<widget>;
还是我完全走错了轨道?我想我对全局shared_ptr理解了这个示例,但对于别名本地不理解。
答案 0 :(得分:3)
std::shared_ptr
会自动销毁指向该对象的所有std::shared_ptr
或将其重新分配给其他对象。
这意味着,如果您存储由std::shared_ptr
管理的对象的指针或引用(这是 aliased 指针),如果{{1 }}管理它已被破坏或修改。
您忽略了示例中最重要的部分,但是在这种情况下:
std::shared_ptr
将std::shared_ptr<int> shared = std::make_shared<int>(7);
int& ptr = *shared;
shared = nullptr;
设置为shared
时,指向的对象将立即被销毁,这意味着指向它的任何指针(如nullptr
)现在都悬空了,并且正在读取或写入会导致UB。
答案 1 :(得分:2)
const shared_ptr<widget>& alias = g_p;
是g_p
的别名。代码中没有别名局部shared_ptr
,它们只是为了完整性而提及:您不能通过创建对全局变量的引用或指针来避免此问题(或多或少只是给它一个不同的名称) -别名-在本地范围内。)
它与您的WidgetPtr
之类的类型别名无关(尽管在为全局shared_ptr
创建本地别名时当然可以使用类型别名。正交)。
换句话说:如果这是错误的代码:
void bad_code()
{
// BAD: passing pointer or reference obtained from a nonlocal smart pointer
// that could be inadvertently reset somewhere inside f or it callees
f(*g_p);
// BAD: same reason, just passing it as a "this" pointer
g_p->func();
}
然后这也是错误的代码:
void also_bad_code(bool maybe)
{
const auto& maybe_g_p_alias = maybe ? g_p : someOtherValue; // Potentially aliases g_p
f(*maybe_g_p_alias);
maybe_g_p_alias->func();
}
答案 2 :(得分:0)
在这种情况下,“别名”表示“同一对象的另一个名称”。
f
以引用widget& w
作为参数。因此,如果您用f(g_p)
进行调用,则在f
和g_p
内都引用同一对象w
。 g_p
是w
的别名。准则规定,您不应调用g_p
(g_p是全局对象),也不应调用f(g_p)
(w是别名的本地对象/全局对象的本地别名)。