gpt4 book ai didi

C++ 类成员 : Stack vs. 堆分配

转载 作者:行者123 更新时间:2023-11-30 02:18:13 25 4
gpt4 key购买 nike

考虑这样一个类

class Element{
public:
// approx. size of ~ 2000 Byte
BigStruct aLargeMember;

// some method, which does not depend on aLargeMember
void someMethod();
}

现在假设在运行时创建了 Element 的许多实例(例如,在运行时有 100,000,000 个实例,同时存在大约 50,000 个实例),并且通常只调用 someMethod(),无需为 aLargeMember 分配内存。(这个说明性的例子源自一个非线性有限元代码,类Element实际上代表一个有限元。)

现在我的问题是:由于 aLargeMember 不是经常需要的,并且考虑到 Element 的大量实例,创建 aLargeMember< 是否有利动态?例如

class Element{
public:
// approx. size of ~ 2000 Byte
std::unique_ptr<BigStruct> aLargeMember;

// only called when aLargeMember is needed
void initializeALargeMember{
aLargeMember = std::unique_ptr<BigStruct>( new BigStruct() );}

// some method, which does not depend on aLargeMember
void someMethod();
}

基本上,这对应于 https://stackoverflow.com/a/36646563/4859499 中给出的建议 4 :

Only use new if there's a clear need, such as:

  • an especially large allocation that would eat up much of the stack (your OS/process will have "negotiated" a limit, usually in the 1-8+ megabyte range)

    • if this is the only reason you're using dynamic allocation, and you do want the lifetime of the object tied to a scope in your function,you should use a local std::unique_ptr<> to manage the dynamicmemory, and ensure it is released no matter how you leave the scope:by return, throw, break etc.. (You may also use a std::unique_ptr<>data member in a class/struct to manage any memory the object owns.)

所以,我的问题是:当前案例中的堆方法是否被视为不良做法?或者在本案中是否有反对堆的任何好的论据?提前致谢!

最佳答案

C++ Class Member: Stack vs. Heap Allocation

不要将基于堆栈的分配与堆分配对象的成员变量混淆。如果您有此类的堆分配对象:

class Element{
public:
// approx. size of ~ 2000 Byte
BigStruct aLargeMember;

// some method, which does not depend on aLargeMember
void someMethod();
}

然后堆栈上没有任何分配。

Since aLargeMember is not required very often, and considering the large number of instances of Element, would it be advantageous to create aLargeMember dynamically?

您所描述的场景确实是动态内存分配的合法候选者,因为不这样做只会让您分配的方式超出您的需要,没有任何好处——所以您别无选择。

Is the heap approach in the present case considered as bad practice?

这个问题有点过于笼统,很容易被解释为基于意见,但在给定片段的上下文中,您似乎指的是在需要使用的情况下分配成员变量的场景-basis,所以去 la lazy initialization为了减轻必须手动维护代码中每个点的初始化的开销,可能更可取。为此,您可以包装对该成员的访问以确保您返回已初始化的内容。只是为了说明,非常不线程安全,思路是这样的:

class Element{
private:
// approx. size of ~ 2000 Byte
std::unique_ptr<BigStruct> aLargeMember;

// A wrapper through which you access aLargeMember
BigStruct& GetLargeMember()
{
if (!aLargeMember)
{
aLargeMember = std::make_unique<BigStruct>();
}

return *aLargeMember;
}

public:
// some method, which might depend on aLargeMember
void someMethod();
};

如果您需要传递它以便在类范围之外使用,那么您将面临悬空引用的危险,因为拥有 unique_ptr 的分配实例可能已经被销毁。如果是这种情况并且您真的想保证不会发生这种情况,那么 unique_ptr 就不合适了,因为您只能移动它。相反,请考虑使用 shared_ptr 并从 GetLargeMember() 返回实际的智能指针。

Or are there any good arguments against the heap in the present case?

不反对在这里使用堆,但至少有几种模式可供您使用。例如,假设您打算创建如此大量的实例,但同时存在的实例要少得多,我会认真考虑 pooling class Element 的实例。

关于C++ 类成员 : Stack vs. 堆分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52485935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com