Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对于C++;类由其他对象组成,使这些成员对象成为指针是一种好的做法吗?_C++_Memory Management - Fatal编程技术网

C++ 对于C++;类由其他对象组成,使这些成员对象成为指针是一种好的做法吗?

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

我想问的是,对于成员“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
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上进行比较