从指向的对象中重新分配 shared_ptr
re-assigning shared_ptr from within object pointed to
考虑以下代码
struct base {
virtual void bar(std::shared_ptr<base>&) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
void bar(std::shared_ptr<base>&obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>(); // re-assign obj
// ...
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x->bar(x); // last line
此代码是否调用 UB? (注意:从最后一行调用时,obj 的重新分配将破坏 call foo2::bar
的 this
对象)。如果之后bar
的数据都没有访问,代码还可以吗?
另一种编码方式是
struct base {
virtual std::shared_ptr<base> bar(std::shared_ptr<base>) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar(std::shared_ptr<base> obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar(x);
在任何情况下哪个应该是安全的,不是吗?此代码中的额外复制是性能问题吗?
编辑。 Chris 回答后,我查看了 shared_from_this
,它允许以下替代实现
struct base : std::enable_shared_from_this<base> {
virtual std::shared_ptr<base> bar() = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar()
{
auto obj = shared_from_this();
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar();
正如这个 link 所指出的,它是安全的而不是 UB 到 delete this
的方法,即使它有点混乱。
Is it safe to `delete this`?
我认为额外的复制不是问题。可以肯定的是,您必须进行概要分析。缺少分析信息,如果是我,我更喜欢第二种方法而不是第一种方法 b/c 程序员更容易理解,但这主要是个人意见。
如果你想让对象更简单地操作指向自身的共享指针等,你可能还想查看 C++11 中的 shared_from_this
模板。
考虑以下代码
struct base {
virtual void bar(std::shared_ptr<base>&) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
void bar(std::shared_ptr<base>&obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>(); // re-assign obj
// ...
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x->bar(x); // last line
此代码是否调用 UB? (注意:从最后一行调用时,obj 的重新分配将破坏 call foo2::bar
的 this
对象)。如果之后bar
的数据都没有访问,代码还可以吗?
另一种编码方式是
struct base {
virtual std::shared_ptr<base> bar(std::shared_ptr<base>) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar(std::shared_ptr<base> obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar(x);
在任何情况下哪个应该是安全的,不是吗?此代码中的额外复制是性能问题吗?
编辑。 Chris 回答后,我查看了 shared_from_this
,它允许以下替代实现
struct base : std::enable_shared_from_this<base> {
virtual std::shared_ptr<base> bar() = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar()
{
auto obj = shared_from_this();
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar();
正如这个 link 所指出的,它是安全的而不是 UB 到 delete this
的方法,即使它有点混乱。
Is it safe to `delete this`?
我认为额外的复制不是问题。可以肯定的是,您必须进行概要分析。缺少分析信息,如果是我,我更喜欢第二种方法而不是第一种方法 b/c 程序员更容易理解,但这主要是个人意见。
如果你想让对象更简单地操作指向自身的共享指针等,你可能还想查看 C++11 中的 shared_from_this
模板。