我有这样的一套: set<weak_ptr<Node>, owner_less<weak_ptr<Node> > > setName;
它工作正常.但我想将它改为无序集.但是,当我这样做时,我得到大约六页的错误.任何想法如何做到这一点?
查看了所有错误消息页面后,我发现了可能有用的行.
/usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
/usr/include/c++/4.7/bits/stl_function.h: In instantiation of ‘bool std::equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::weak_ptr<Node>]’:
Run Code Online (Sandbox Code Playgroud) 我想将原始指针成员包装到某个智能指针,以防止在开发类中删除.指针下对象的所有者在类之外.所以,看起来boost::shared_ptr和std::auto_ptr不适合.以下是一个简化示例:
class Foo {
boost::weak_ptr<Bar> m_bar;
public:
void setBar(const Bar *bar) { // bar created on heap
m_bar = bar; // naturally compilation error
}
};
Run Code Online (Sandbox Code Playgroud)
当然,它会导致编译错误.weak_ptr从原始指针(如果存在)初始化的正确方法是什么?
请考虑到我的经验不足,但我不明白这一点std::owner_less.
我一直在显示一个map与weak_ptr作为,不建议关键,因为一个过期的weak_ptr键将打破地图,实际上是:
如果它到期,则容器的订单被破坏,并且之后尝试使用容器将给出未定义的行为.
这种行为有多未定义?我问的原因是因为文档说owner_less:
此函数对象提供std :: weak_ptr和std :: shared_ptr的基于所有者(而不是基于值)的混合类型排序.顺序是两个智能指针只有当它们都是空的或它们都管理同一个对象时才比较等价,即使get()获得的原始指针的值不同(例如因为它们指向不同的子对象)同一个对象)
再一次,这是我缺乏经验的谈话,但听起来并不会map被过期weak_ptr完全破坏:
返回weak_ptr对象是否为空或者它所属的所有者组中是否没有更多shared_ptr.
过期的指针在锁定时充当空的weak_ptr对象,因此不能再用于恢复拥有的shared_ptr.
听起来它可能比完全未定义更加松弛.如果一个人的实现删除了过期的weak_ptrs并且根本没有或没有使用任何延迟的,那么这个行为何时变得不确定?
如果一个人的实现不考虑订单,但只需要一种方便的方法来将weak_ptrs与数据相关联,那么行为是否仍未定义?换句话说,会find开始返回错误的密钥吗?
我在文档中可以找到的唯一问题是上面提到的,过期的weak_ptrs将返回等价物.
根据这些文档,对于不依赖于排序也不使用过期weak_ptrs的实现,这不是问题:
联想
关联容器中的元素由其键引用,而不是由它们在容器中的绝对位置引用.
有序
容器中的元素始终遵循严格的顺序.所有插入的元素按此顺序给出一个位置.
地图
每个元素将键与映射值相关联:键用于标识主要内容为映射值的元素.
这听起来好像如果一个实现不涉及顺序也没有使用过期的weak_ptrs那么没有问题,因为值是由键而不是顺序引用的,所以find过期weak_ptr将返回可能是另一个weak_ptrs值,但是因为没有用它在这个特定的实现中,除了erased之外,没有问题.
我可以看到如何使用weak_ptr排序或过期的weak_ptrs可能是一个问题,无论应用程序是什么,但所有行为似乎远未定义,所以a map或set似乎没有完全被过期打破weak_ptr.
是否有更多的技术解释map,weak_ptr以及owner_less那反驳这些文档,我的解释是什么?
有时我真的很确定我想要循环依赖指针,并且循环中的每个对象都应该能够使用他的指针(所以它不能是weak_ptr).
我的问题是:这是否意味着我的设计不好?
如果我想实现图形怎么办?我可以使用智能指针吗?在图表中有循环,但使用weak_ptr我不能使用" - >".我能做什么?
我在StackOverflow上阅读了一些文章,参考和主题,但看起来我仍然没有得到智能指针.真的,为什么不存在一些带有" - >"的weak_ptr变体?
我有一组Creature对象,使用std::make_shared和创建并拥有在我的应用程序的一部分中std::shared_ptr.
我还跟踪一个选择的零个或一个Creature在World使用对象std::weak_ptr<Creature>.
void World::SetSelection(const std::shared_ptr<Creature>& creature) {
selection = creature;
}
std::shared_ptr<Creature> World::GetSelection() const {
return selection.lock();
}
Run Code Online (Sandbox Code Playgroud)
调用者GetSelection负责检查指针是否为空.如果是,那意味着目前没有选择.
这一切都完全符合我的喜好:当选定Creature的自然原因(应用程序中的其他地方)死亡时,再次GetSelection开始返回nullptr,就像没有选择任何东西一样.
但是在这种情况下,World::selection成员仍然指向std::shared_ptr控制块.这可能非常大,因为我std::make_shared用来创建我的Creature对象(我意识到Creature对象在正确的时间被正确销毁但仍然分配了它的内存).我正在考虑GetSelection改为:
std::shared_ptr<Creature> World::GetSelection() {
const auto ret = selection.lock();
if (!ret)
selection.reset();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
一旦我注意到它不再需要,它就会释放内存.令人讨厌的是,这个版本GetSelection不可能const.
GetSelection在这种情况下哪个版本被认为是最佳做法?
如果在模板化代码中发生类似的事情,那么答案是否会改变,哪些sizeof(T)是未知的并且可能是巨大的?或者在C++ 14中std::make_shared<T[]> …
例如,有一个函数可以找到一个对象,如果找到了对象则返回shared_ptr,并且必须以某种方式指示没有找到对象.
std::vector<std::shared_ptr> Storage::objects;
std::shared_ptr<Object> Storage::findObject()
{
if (objects.find)
{
return objects[x];
}
else
{
return nullptr;
}
}
std::shared_ptr<Object> obj = Storage::findObject();
if (obj)
{
print("found");
}
else
{
print("not found");
}
Run Code Online (Sandbox Code Playgroud)
返回使用nullptr隐式初始化的shared_ptr是否正确?它会起作用,但可以这样做吗?或者我应该返回shared_ptr默认构造而不是?
怎么会是weak_ptr?检查空weak_ptr已被返回的正确方法是什么?by weak_ptr :: expired函数还是有其他方法吗?如果通过weak_ptr :: expired检查是唯一的方法那么我如何区分该函数返回空指针,或者对象刚被删除(多线程环境)?
我正在尝试使用循环引用boost::shared_ptr,并设计了以下示例:
class A{ // Trivial class
public:
i32 i;
A(){}
A(i32 a):i(a){}
~A(){
cout<<"~A : "<<i<<endl;
}
};
shared_ptr<A> changeI(shared_ptr<A> s){
s->i++;
cout<<s.use_count()<<'\n';
return s;
}
int main() {
shared_ptr<A> p1 = make_shared<A>(3);
shared_ptr<A> p2 = p1;
shared_ptr<A> p3 = p2;
shared_ptr<A> p4 = p3;
p1 = p4; // 1) 1st cyclic ref.
cout<<p1.use_count()<<'\n';
p1 = changeI(p4); // 2) 2nd cyclic ref.
cout<<p1.use_count()<<'\n';
// putchar('\n');
cout<<endl;
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
4
5
4
~A : 4
Run Code Online (Sandbox Code Playgroud)
是不是我误解了所提到的循环引用boost::shared_ptr?因为,我预计间接引用的不同输出思维p1 …
为了查看weak_ptr是否指向有效对象,创建临时shared_ptr似乎效率低下.我甚至不想访问该对象.这是因为我有一个从shared_ptr的向量返回weak_ptr的函数,如果它返回一个空的weak_ptr,那么这意味着该对象不存在该GUID.
所以我只是测试对象是否存在.
有没有另一种方法来检查weak_ptr是否为空,而不创建shared_ptr?
我理解通过从类的构造函数中调用shared_from_this()来获取shared_ptr是不可能的,因为该对象尚未构造.但是有可能从构造函数中获取对象的weak_ptr吗?一些提升论坛帖子讨论"weak_from_raw()"方法表明它可能是有可能的.
编辑:提升形式讨论weak_from_raw http://lists.boost.org/boost-users/2010/08/61541.php
它可以这样实现:
std::shared_ptr<T> operator->() {
auto shared = lock();
if(shared == nullptr) {
throw std::bad_weak_ptr(); // or some other exception
}
return shared;
}
Run Code Online (Sandbox Code Playgroud)
为什么weak_ptr 的作者决定不使用operator->?(他们一定想到了)
我可以想到潜在的原因,但我想知道官方的原因是什么,如果存在的话.可能的原因:
如果您对返回的shared_ptr的生命周期感到困惑,请参阅此文章.
另外,有人问为什么如果你希望它没有过期,会使用weak_ptr?答案:周期.