Bor*_*ein 6 c++ smart-pointers weak-ptr c++11
我有一个遵循这种模式的课程:
class Foo
{
public:
// Create a Foo whose value is absolute
Foo(int x) : other_(0), a_(x) {}
// Create a Foo whose value is relative to another Foo
Foo(Foo * other, int dx) : other_(other), a_(dx) {}
// Get the value
double x() const
{
if(other_)
return other_->x() + a_;
else
return a_;
}
private:
Foo * other_;
int a_;
};
Run Code Online (Sandbox Code Playgroud)
这些Foo对象都归Bar:
class Bar
{
public:
~Bar() { for(int i=0; i<foos_.size(); i++) delete foos_[i]; }
private:
vector<Foo*> foos_;
};
Run Code Online (Sandbox Code Playgroud)
当然,这是获得想法的简化示例.我保证没有Foos的循环,并且链接的Foos都属于同一个实例Bar.到现在为止还挺好.做事的C++ 11的方式,我会用vector< unique_ptr<Foo> > foos_;的Bar,并通过foos_[i].get()作为一个潜在的参数Foo的构造函数.
有交易:
这是一个GUI应用程序,用户可以随意交互删除一些Foo.预期的行为是,如果foo1删除,并且foo2相对于foo1,则foo2变为现在"绝对":
void Foo::convertToAbsolute() { a_ += other_->x(); other_ = 0; }
void usageScenario()
{
Foo * foo1 = new Foo(42);
Foo * foo2 = new Foo(foo1, 42);
// Here, foo1->x() = 42 and foo2->x() = 84
foo1->setX(10);
// Here, foo1->x() = 10 and foo2->x() = 52
delete foo1;
// Here, foo2->x() = 52
}
Run Code Online (Sandbox Code Playgroud)
我知道可以使用原始指针,通过使用带有后向指针的DAG结构来实现它,因此Foo知道谁"依赖于它们",并且可以在删除之前通知它们(此处和此处详述可能的解决方案).
我的问题是:你会以同样的方式处理它吗?有没有办法使用标准的C++ 11智能指针来避免使用显式的反向指针,然后避免areRelativeToMe_[i]->convertToAbsolute();在析构函数中明确地调用Foo?我正在思考weak_ptr,本着以下精神:
class Foo { /* ... */ weak_ptr<Foo> other_; };
double Foo::x() const
{
if(other_.isExpired())
convertToAbsolute();
// ...
}
Run Code Online (Sandbox Code Playgroud)
但问题是convertToAbsolute()需要相对Foo仍然存在.所以我需要一个非拥有的智能指针,可以告诉"此引用在逻辑上已过期",但实际上延长了引用对象的生命周期,直到不需要它为止.
它可以被视为weak_ptr延长寿命,直到它不与任何其他共享weak_ptr:
class Foo { /* ... */ extended_weak_ptr<Foo> other_; };
double Foo::x() const
{
if(other_.isExpired())
{
convertToAbsolute();
other_.reset(); // now the object is destructed, unless other
// foos still have to release it
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者喜欢shared_ptr具有不同所有权级别的人:
class Bar { /* ... */ vector< multilevel_shared_ptr<Foo> foos_; };
class Foo { /* ... */ multilevel_shared_ptr<Foo> other_; };
void Bar::createFoos()
{
// Bar owns the Foo* with the highest level of ownership "Level1"
// Creating an absolute Foo
foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(42), Level1) );
// Creating a relative Foo
foos_.push_back( multilevel_unique_ptr<Foo>(new Foo(foos_[0],7), Level1) );
}
Foo::Foo(const multilevel_unique_ptr<Foo> & other, int dx) :
other_( other, Level2 ),
// Foo owns the Foo* with the lowest level of ownership "Level2"
a_(dx)
{
}
double Foo::x() const
{
if(other_.noLevel1Owner()) // returns true if not shared
// with any Level1 owner
{
convertToAbsolute();
other_.reset(); // now the object is destructed, unless
// shared with other Level2 owners
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?
全部Foo归 拥有Bar。因此,所有删除都Foo发生在Bar方法中。所以我可能会在里面实现这个逻辑Bar:
void Bar::remove(Foo* f)
{
using namespace std::placeholders;
assert(std::any_of(begin(foos_), end(foos_),
std::bind(std::equal_to<decltype(f)>(), f, _1));
auto const& children = /* some code which determines which other Foo depend on f */;
std::for_each(begin(children), end(children),
std::mem_fn(&Foo::convertToAbsolute));
foos_.remove(f);
delete f; // not needed if using smart ptrs
}
Run Code Online (Sandbox Code Playgroud)
这将确保在调用其依赖项时过期Foo仍然存在。convertToAbsolute
如何计算children由您决定。我可能会让每个都Foo跟踪自己的子级(循环非拥有指针),但您也可以在内部跟踪它,或者按需Bar搜索以在需要时重新计算它。foos_
| 归档时间: |
|
| 查看次数: |
432 次 |
| 最近记录: |