我要问的是关于会员" mylist"的更好的做法:
像这样声明mylist:
class MyClaz {
std::list<string> mylist;
...
}
或者声明这样:
class MyClaz {
std::list<string> *mylst;
MyClaz();
...
}
MyClaz::MyClaz() {
myList = new std::list<string>();
}
// plus destructor to delete myList
在第一种情况下,当创建MyClaz实例时,是否会自动分配mylist?当MyClaz被销毁时,它会被正确清理吗?
有没有理由使用第二种情况?这似乎更危险。
答案 0 :(得分:10)
仅在需要时谨慎使用指针。没有指针有许多优点,包括不必手动管理对象的生命周期和数据局部性。问题应该是是否有任何理由使用第二个案例......
答案 1 :(得分:2)
要回答您的第一个问题,是的,mylist
将自动分配并自动销毁,这就是为什么第二种方法一般都不好。
请注意,自动创建的mylist
将是一个空字符串。
答案 2 :(得分:2)
将这些成员对象作为指针是好的做法吗?
通常没有 1 。使用C ++标准库容器,尤其没有。
sizeof(std::list<string>)
非常小,课程管理着自己的一生。每个列表元素都将被列表析构函数销毁,这将由您自动创建的析构函数自动调用。
使用new
创建容器完全没有意义。
在第一种情况下,当创建MyClaz实例时,是否会自动分配mylist?当MyClaz被销毁时,它会被正确清理吗?
是的,是的。
mylist
的构造函数调用MyClaz
的默认构造函数,mylist
的析构函数调用MyClaz
的析构函数(如果你不这样做)写一个 - 编译器为你创建一个)
1 - 有一些原因你应该使用指针(例如PIMPL,多态),但在这些情况下你使用智能指针(std::shared_ptr
,{ {1}}),而非原始指针(std::unique_ptr
)。
答案 3 :(得分:1)
在容器中没有任何意义,因为那时你必须担心在析构函数中删除它。最好的方法是使用method1。也许你可能想要一个std :: list的引用而不是实际的对象。
此外,如果您使用STL,最好使用智能指针(例如std :: shared_ptr),这样您就不必担心在其上调用delete。
std::shared_ptr<std::list<string>> mylist;
//in constructor
mylist = std::make_shared<std::list<string>>();
//in destructor it will be deleted automatically
//if you want to have a list of references rather than objects themselves
std::list<std::shared_ptr<string>> mylist;
希望它有所帮助。
答案 4 :(得分:1)
在大多数情况下,使用对象而不是指针是有意义的。但是,有一些例外,使用指针是有意义的。了解例外情况很好。
我发现最令人信服的原因是,当列表预计在大多数时间为空时,将列表作为成员变量是很昂贵的。构建一个可以避免大多数对象的列表的内存和时间成本。
以下是CAD / CAE应用程序中经常出现的简化示例。
class Attribute;
class Entity
{
std::list<Attribute*>* attributes;
};
class Attribute: public Entity
{
};
大多数Entity
都没有Attribute
,但会有很多人Entity
。就Part
而言,这些是使用指定的数据。 Entity
可能来自Color
,可能具有Density
等视觉属性,Face
等材质属性。但是,Part
的{{1}}可能有自己的Color
。如果没有自己的Color
,则Face
会继承其Part
Color
。
使用std::list<Attribute*>*
代替std::list<Attribute*>
的关键原因是,当大多数对象不需要时,为每个对象创建一个列表可能会很昂贵。指针将分配给构造函数中的NULL
。当一个对象需要在列表中有一个项目时,将从堆中分配一个列表并在此后使用。
额外的逻辑伴随着额外的维护负担,但成本可以证明收益是合理的。
<强>更新强>
由于各种原因,我们仍然需要在Windows 7(64位)上使用Microsoft Visual Studio 2008。在那个平台上,
sizeof(std::list<Attribute*>)
是48
sizeof(std::vector<Attribute*>)
是40
sizeof(std::vector<Attribute*>*)
是8。
使用g ++ 4.7.3(32位),大小为:
sizeof(std::list<Attribute*>)
是8
sizeof(std::vector<Attribute*>)
是12
sizeof(std::vector<Attribute*>*)
是4。
根据您的平台,对象与指针的额外成本可能过高。必须根据平台上的数字进行判断。
答案 5 :(得分:1)
当您考虑指针时,请考虑生命周期和费用。如果你有一个指针,那么当你想要使用它时,无论指针指向指针可能存在哪些 ,你的代码将处理这两种情况 。虽然这可以提供很大的灵活性并且可以提高性能,但这需要付出代价。
C ++是一种可以让你做任何事情的语言。 假设您知道自己在做什么。
所以问题的答案是,只有当你知道为什么需要它们时才使用指针。
如果,在你的脑海中,你正在思考,“也许指针可能更好”,那么答案是否定的,他们不是。为什么?因为你不清楚使用指针的成本,从长远来看,这对你的代码来说弊大于利。请记住,C ++再次假设您知道自己在做什么。
另一方面,如果您决定不使用指针,那么您应该使用什么?完全按照您的方式使用它:
class MyClaz {
std::list<std::string> mylist; //I assume you meant std::string here
...
}
目前,信任编译器。不要担心按值复制。担心你的代码和你做它想做的事情有多好和多么清楚。这是一个很好的做法。
所以一般来说,良好的做法是只在你有充分理由这样做时才做出改变。