我想实现这个:
这是否可以结合使用不同的智能指针?
答案 0 :(得分:2)
让我们考虑角色(现在忽略线程):
对象A拥有B的生命周期
对象C是B生命周期的观察者
你没有说A和C之间是否存在关系,所以我假设A知道C在其构造函数中的含义(让我们使用C作为可配置的工厂)。
B的生命事件有两个地方可以创建观察 - B的构造函数/析构函数(坏 - 紧耦合)或中间工厂(更好 - 松散耦合)。
所以:
#include <memory>
#include <algorithm>
struct B {
};
struct C {
std::shared_ptr<B> make_b() {
auto p = std::shared_ptr<B>(new B(), [this](B *p) {
this->remove_observer(p);
delete p;
});
add_observer(p.get());
return p;
}
private:
void add_observer(B *p) {
observers_.push_back(p);
}
void remove_observer(B *p) {
observers_.erase(std::remove(std::begin(observers_), std::end(observers_), p),
std::end(observers_));
}
std::vector<B *> observers_;
};
struct A {
A(C &factory)
: b_(factory.make_b()) {}
std::shared_ptr<B> b_;
};
int main() {
// note: factory must outlive a1 and a2
C factory;
A a1(factory);
A a2(factory);
}
请注意,虽然我使用了shared_ptr
,但在这种情况下我可以轻松使用unique_ptr
。然而,我会将A与指针中的删除类型相结合 - 所以我要么必须创建我自己的类型删除删除类型,要么更紧密地耦合A到C(我想避免)。
答案 1 :(得分:1)
Object A owns an Object B (has a pointer to it)
When Object A is destroyed, Object B is destroyed too.
Object C has a std::vector of pointers to Object B-s.
When Object B is destroyed, remove its pointer from Object C's vector.
对象A的生命周期由shared_ptr
管理。
它可以完全控制B
的生命周期:
struct A {
std::unique_ptr<B> b;
};
或
struct A {
B b;
};
我们将添加observe_B
方法:
struct A {
std::unique_ptr<B> b;
B* observe_B() { return b.get(); }
B const* observe_B() const { return b.get(); }
};
我们将逻辑const。对于我们有实际B
的情况,我们只是&
而不是.get()
。因此,我们不再关心如何分配B
(指针或A的正文)。
现在我们有一个相对复杂的生命周期请求。明智地使用shared_ptr
可能适用于此。实际上,shared_from_this
:
struct A:std::enable_shared_from_this<A> {
std::unique_ptr<B> b;
B* observe_B() { return b.get(); }
B const* observe_B() const { return b.get(); }
std::shared_ptr<B const> get_shared_B() const {
return {shared_from_this(), observe_B()};
}
std::shared_ptr<B> get_shared_B() {
return {shared_from_this(), observe_B()};
}
};
这里我们使用&#34;别名构造函数&#34;共享指针,用于返回指向非共享对象的共享指针。它的目的正是为了这个目的。我们使用A
的共享生命周期语义,但将其应用于B*
。
在C
中,我们只存储vector<weak_ptr>
。
struct C {
std::vector<std::weak_ptr<B>> m_Bs;
};
现在,当A
消失时,weak_ptr
到&#34;包含&#34; B
失去了最后的强烈参考。当你.lock()
时,它现在失败了。
struct C {
std::vector<std::weak_ptr<B>> m_Bs;
void tidy_Bs() {
auto it = std::remove_if( begin(m_Bs), end(m_Bs), [](auto&& x)->bool{return !x.lock();});
m_Bs.erase(it, end(m_Bs));
}
};
tidy_Bs
删除所有&#34;悬空&#34; weak_ptr
中B
到m_Bs
。{/ p>
要进行迭代,我通常会这样做:
struct C {
std::vector<std::weak_ptr<B>> m_Bs;
void tidy_Bs() {
auto it = std::remove_if( begin(m_Bs), end(m_Bs), [](auto&& x)->bool{return !x.lock();});
m_Bs.erase(it, end(m_Bs));
}
template<class F>
void foreach_B(F&& f) {
tidy_Bs();
auto tmp = m_Bs;
for (auto ptr:m_Bs)
if (auto locked = ptr.lock())
f(*locked);
}
};
为f
向量中的每个仍然存在的B&
传递B
一个m_Bs
。虽然它在那里,但它清理了死者。
我复制了这个向量,因为在迭代时,有人可以去改变m_Bs
的内容,并且在发生这种情况时我不能在m_Bs
上进行迭代。
可以在A
未管理shared_ptr
的情况下完成整个技术;但是B
必须由shared_ptr
管理。
请注意,通常&#34;通常&#34;如果A
当前C
.lock()
包含B
A
,C
可能无法实际销毁df['e'] = np.where((df['a'] == 1) & (df['b'] == 1), -1, 1)
print (df)
a b c e
0 1 1 0 -1
1 1 -1 1 1
2 1 0 0 1
。实际上,除了使SELECT
date,
eventype,
count(*) AS count,
(UNIX_TIMESTAMP(date)) DIV 600 AS group_field
FROM vpnhistory
WHERE partnername REGEXP 'CESAR'
GROUP BY group_field;
崩溃之外,没有办法避免这种情况。