只是,我已经运行到一个概念上的问题。 在我当前的项目,感觉就像我过度使用升压smart_ptr
和ptr_container
库。 我创建boost::ptr_vectors
在许多不同的对象,并调用转移()方法从一个移动某些指针boost::ptr_vector
到另一个。
这是我的理解,它清楚地显示堆上分配对象的所有权是很重要的。
我的问题是,它希望利用这些Boost库创建属于对象堆上分配的成员,但然后通过使用普通的指针这些成员get()
做任何处理的情况下。
例如...一个游戏可能有属于它的瓦片的集合。 它可能是有意义的建立在这些瓷砖boost::ptr_vector
。 当比赛结束这些砖应自动释放。
但是,如果我想要把这些砖包:对象是暂时的,我应该创建另一个boost::ptr_vector
收入囊中,并通过游戏的瓷砖转移到袋transfer()
或者我应该创建一个std::vector<Tile*>
其中瓷砖*的参考瓷砖在游戏中并传递给袋?
谢谢。
**编辑我要指出的是,在我的例子,比赛将有一个袋子对象作为成员。 袋子只装满瓷砖游戏拥有。 所以袋不会没有游戏存在。
您应该只使用拥有智能指针和指向容器那里的所有权的交接清楚。 不要紧,如果对象是暂时的或不 - 所有重要的是它是否具有所有权或没有(和,因此,以前的主人是否放弃所有权)。
如果您创建的指针的临时矢量只是将它传递给一些其他的功能,与原ptr_vector
还引用了所有这些对象,没有过户,因此,你应该使用普通vector
的临时对象-就像你使用原始指针到从一个单一对象传递ptr_vector
给带有指针,但不将其存储在任何地方的功能。
在我的经验中,有三个是突然出现的主要所有制形式。 我会打电话给他们树,DAG和图形。
最常见的是一棵树。 母公司拥有其子女,这反过来又拥有自己的孩子等等。 auto_ptr的,scoped_ptr的,裸指针和升压ptr_x类是你通常在这里看到。 在我看来,他们传达没有所有权的语义在所有一般应避免裸指针。
第二个最常见的是DAG。 这意味着你可以有共同的所有权。 父母拥有的孩子也可能是其他孩子家长拥有的孩子。 该TR1和升压shared_ptr的模板是这里的主角。 引用计数是一个可行的策略,当你有没有周期。
第三个最常见的是全图。 这意味着,你可以有周期。 有打破这些周期和在错误的一些可能的来源成本返回到DAG的一些策略。 这些一般通过TR1或升压转换器的模板了weak_ptr代表。
全图不能被分解成一个DAG使用的weak_ptr是不能轻易用C有待解决的问题++。 唯一的好处理程序是垃圾回收方案。 他们也是最普遍的,能够处理其他两个方案也非常的好。 但他们的共性是有代价的。
在我看来,你不能过度使用ptr_x容器类或auto_ptr的,除非你真的应该使用对象来代替指针的容器的容器。 shared_ptr的可以被滥用。 仔细想想你是否真的不需要一个DAG。
当然,我认为人们应该只是使用scope_ptrs代替升压ptr_x类的容器,但将不得不等待的C ++ 0x。 :-(
最有可能的,你要寻找的解决方案
std::vector<Tile>
没有必要对指针的大部分时间。 该载体已经照顾包含的对象的内存管理人员的。 瓷砖是由游戏拥有的,不是吗? 为了让这个明确的方法是把对象本身在游戏类 - 只在您通常需要指针和动态分配的单个对象的情况是,如果你需要1)多态性,或2)共享所有权。
但是,指针应该是例外,而不是规则。
boost::ptr_vector
只是为了提高使用指针的向量的语义。 如果,在你的例子,原来的阵列可以被毁灭,而临时组向量是在使用,那么你绝对应该使用的矢量shared_ptr
s到防止它们仍在使用被删除。 如果不是,则指针的一个普通旧载体可以是适当的。 无论您选择std::vector
或boost::ptr_vector
其实并不重要,只是在使用矢量代码有多好看起来。
在你的游戏瓷砖例子,我的第一本能是创建一个vector<Tile>
,而不是一个vector<Tile*>
或ptr_vector。 然后使用指针的瓷砖,请你,而不用担心所有权的全部,只要持有指针的对象生存期不会超过瓷砖的载体。 你说,当游戏结束时它只是破坏,所以应该不是难事。
当然也有可能是原因,这是不可能的,比如因为瓷砖是一个多态基类,和瓷砖本身并不都是同一类的。 但是,这是C ++,而不是Java,而不是每一个问题总是需要动态多态性。 但是,即使你真的需要指针,你仍然可以使这些指针的副本没有任何所有权的语义,前提是对象的范围和保管期限指着被理解为比使用指针的范围和持续时间更宽:
int main() {
vector<Tile*> v;
// fill in v, perhaps with heap objects, perhaps with stack objects.
runGame(v);
}
void runGame(const vector<Tile*> &v) {
Tile *firsttile = v[0];
vector<Tile*> eventiles;
eventiles.push_back(v[2]);
eventiles.push_back(v[4]);
// and so on. No need to worry about ownership,
// just as long as I don't keep any pointers beyond return.
// It's my caller's problem to track and free heap objects, if any.
}
如果游戏拥有瓷砖,则游戏responcable因为有deltion。
这听起来像袋子实际上从未ownes的对象所以它不应该是responcable删除它们。 因此,我将在游戏对象中使用ptr_vector。 但在袋子使用一个std ::向量。
注意:使用包检索指向从包里瓷砖我不会让任何人。 他们应该只能够检索referenceto从包装袋中瓦。
如果瓷砖放在袋子,有人偷了袋你失去所有的瓷砖。 因此瓷砖,althought即暂时的,但它们属于袋的时间很短。 你应该在这里转移所有权的,我想。
但更好的意见是不要乱用的所有权,因为我不明白为什么它需要在这种特殊情况下。 如果有幕后的东西,去,让你的选择。
我同意使用矢量,而不是右跳进堆上分配T是一个很好的本能,但我可以很容易地看到瓷砖是用于在拷贝构造是昂贵的一种类型,这可能会妨碍载体的发展战略务实。 当然,这可能是最好的一个列表,而不是一个向量解决...