C++ 对于C++;类由其他对象组成,使这些成员对象成为指针是一种好的做法吗?
我想问的是,对于成员“mylist”,什么是更好的做法: 像这样声明mylist:C++ 对于C++;类由其他对象组成,使这些成员对象成为指针是一种好的做法吗?,c++,memory-management,C++,Memory Management,我想问的是,对于成员“mylist”,什么是更好的做法: 像这样声明mylist: class MyClaz { std::list<string> mylist; ... } class MyClaz { std::list<string> *mylst; MyClaz(); ... } MyClaz::MyClaz() { myList = new std::list<string>(); } // plus destructo
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
classmyclaz{
std::列表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
classmyclaz{
std::list*mylst;
MyClaz();
...
}
MyClaz::MyClaz(){
myList=新标准::列表();
}
//加上析构函数删除myList
在第一种情况下,在创建MyClaz实例时是否会自动分配mylist?当MyClaz被摧毁时,它会得到适当的清理吗
是否有任何理由使用第二种情况?这似乎更危险。只有在需要时才谨慎使用指针。没有指针有很多优点,包括不必手动管理对象的生存期和数据局部性。问题应该是是否有任何理由使用第二种情况…要回答第一个问题,是的,
mylist将自动分配并自动销毁,这就是为什么第二种方法通常不好的原因
请注意,自动创建的mylist
将是一个空字符串
使这些成员对象成为指针是一种好的做法吗
主要是1号。用C++标准库容器,特别是NO.<
sizeof(std::list)
非常小,类管理自己的生存期。每个列表元素都将被列表析构函数销毁,它将由您自动创建的析构函数自动调用
使用new
创建容器完全没有抓住要点
在第一种情况下,在创建MyClaz实例时是否会自动分配mylist?当MyClaz被摧毁时,它会得到适当的清理吗
对,对
mylist
的默认构造函数由MyClaz
的构造函数调用,mylist
的析构函数由MyClaz
的析构函数调用(如果您不编写,编译器会为您创建一个)
1-使用指针有一些原因(例如PIMPL、多态性),但在这些情况下,您使用智能指针(std::shared_ptr
,std::unique_ptr
),而不是原始指针(T*
)。对容器进行“新建”没有意义,因为这样您就不得不担心在析构函数中删除它。最好的方法是使用方法1。也许您需要一个std::引用列表,而不是实际的对象
此外,如果您正在使用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;
std::shared_ptr mylist;
//在构造函数中
mylist=std::make_shared();
//在析构函数中,它将被自动删除
//如果您想要一个引用列表而不是对象本身
std::列表mylist;
希望有帮助。在大多数情况下,使用对象而不是指针是有意义的。但是,也有例外情况,使用指针是有意义的。知道例外情况很好
我发现的最令人信服的原因是,当列表大部分时间都是空的时,将列表作为成员变量是非常昂贵的。对于大多数对象来说,构建一个列表需要花费内存和时间
下面是一个在CAD/CAE应用程序中常见的简化示例
class Attribute;
class Entity
{
std::list<Attribute*>* attributes;
};
class Attribute: public Entity
{
};
类属性;
类实体
{
std::列表*属性;
};
类属性:公共实体
{
};
大多数实体
s将不具有属性
s,但许多实体将具有属性。就实体而言,这些是使用指定数据的。可能从实体
派生的零件
,可能具有视觉特性,如颜色
,材料特性,如密度
。但是,零件的面
可能有自己的颜色
。如果没有自己的颜色
,则面
将继承其包含的部分
的颜色
使用std::list*
而不是std::list
的关键原因是,当大多数对象不需要列表时,为每个对象创建一个列表可能会很昂贵。指针将被分配到构造函数中的NULL
。当一个对象需要在列表中有一个项时,将从堆中分配一个列表,并从此使用
额外的逻辑带来了额外的维护负担,但成本可以为收益辩护
更新
由于各种原因,我们仍然需要在Windows 7(64位)上使用Microsoft Visual Studio 2008。在那个平台上,
sizeof(std::list)
48
sizeof(std::vector)
40
sizeof(std::vector*)
是8
对于g++4.7.3(32位),大小为:
sizeof(std::list)
为8
sizeof(std::vector)
12
sizeof(std::vector*)
为4
根据您的平台,对象与指针的额外成本可能会过高。必须根据平台上的数字做出判断。当你考虑指针时,考虑寿命和成本。当你有一个指针时,你实际上是在说,当你想使用它时,指针指向的任何东西可能存在,也可能不存在,你的代码将处理这两种情况。虽然这提供了很大的灵活性并可以提高性能,但这是有代价的
- 您不能再假设所指向的内容存在,并且需要代码来处理这两种情况——当它存在时和当它不存在时李>
- 您现在必须非常小心如何使用STL-例如:将在poi上进行比较