将对象成员显式放在堆上(通过new)是否被视为不礼貌/不良做法?我认为您可能希望允许客户端选择内存区域来实例化对象。我知道可能存在堆成员可能被接受的情况。如果您知道某种情况,请说明一下吗?
答案 0 :(得分:13)
如果你有一个专为复制语义设计的类,并且你不必要地分配/释放一堆内存,我可以看到这是不好的做法。但总的来说,事实并非如此。有很多类可以使用堆存储。只要确保你没有内存泄漏(在析构函数中释放内容,引用计数等),你就可以了。
如果您想要更多灵活性,请考虑让您的用户指定Allocator。我会解释一下。
某些课程,例如std::vector
,字符串,地图等需要它们所代表的数据结构的堆存储。它不被认为是不礼貌的;当你有一个自动分配的vector
时,用户应该知道在调用vector
构造函数时分配了一个缓冲区:
void foo() {
// user of vector knows a buffer that can hold at least 10 ints
// gets allocated here.
std::vector<int> foo(10);
}
同样,对于std::string
,您知道有一个内部堆分配char*
。每个string
实例是否有一个通常取决于STL实现;通常他们被引用计数。
但是,对于几乎所有的STL类,用户执行可以选择放置的位置,因为他们可以指定分配器。 vector
定义如下:
template <typename T, typename Alloc = DefaultAllocator<T> >
class vector {
// etc.
};
在内部,vector
使用Alloc
(默认为T的默认分配器)来分配缓冲区和它可能需要的其他堆存储。如果用户不喜欢默认分配策略,他们可以指定自己的策略:
vector<int, MyCustomAllocator> foo(10);
现在,当构造函数分配时,它将使用MyCustomAllocator
而不是默认值。以下是一些details on writing your own STL allocator。
如果你担心在你的班级中使用堆来存储某些存储可能是“不礼貌”,你可能会考虑给你的类用户这样一个选项,以便他们可以指定事情的方式如果您的默认策略不符合他们的需要,则分配。
答案 1 :(得分:10)
我根本不认为这是不好的做法。您可能希望通过new显式分配成员变量的原因有很多种。这里有一些不在我的脑海里。
另一方面,如果您的用户创建了很多类的实例以供在堆栈上使用,那么使用对象代替成员变量的指针将是有利的,因为堆分配/解除分配比较慢。在这种情况下避免堆更有效,当然考虑到上面的第一个子弹。
答案 2 :(得分:1)
在课堂上放置其成员的重要性不如课程中的管理权限;即客户端和子类不应该担心对象的成员变量。
最简单的方法是使它们成为堆栈变量。但在某些情况下,例如,如果您的类具有动态数据结构,如链接列表,则没有意义。
但是如果你确保自己的对象在自己之后清理,那对大多数应用程序来说应该没问题。
答案 3 :(得分:0)
如果您有课程:
class MyOtherClass;
class MyClass
{
MyOtherClass* m_pStruct;
};
然后,MyClass的客户端没有真正选择如何分配m_pStruct。
但是客户决定如何在堆栈上或堆上分配MyClass类本身:
MyClass* pMyClass = new MyClass;
或
MyClass myClass;