gpt4 book ai didi

派生类的 C++ 数组与基类指向派生对象的指针数组 - 为什么分配的内存量如此不同?

转载 作者:太空狗 更新时间:2023-10-29 23:42:08 25 4
gpt4 key购买 nike

我需要澄清一个我不太明白的问题。使用以下两种情况,我认为分配的内存量大致相同。但是,方案 2 给了我一个 bad_alloc一段时间后出现异常,并且似乎在疯狂地消耗内存(使用 Window 的任务管理器作为分配给进程的内存量的代理)。以下是使用 MSVC10 在 Windows 32bit 上编译的。

假设我有以下基类:

template<class T>
class Base
{
protected:
T x;
public:
Base() {}
Base(T _x) : x(_x){}
virtual bool func() = 0;
};

现在,至于派生类:

template<class T>
class Derived : public Base<T>
{
public:
Derived() {}
Derived(T _x) : Base(_x){}
bool func() { return true; };
};

现在考虑两种情况。首先,分配一个 Derived 类的动态数组,并用 Derived 对象填充它,即:

int main()
{
int size = SOME_LARGE_NUMBER;
Derived<int>* d = new Derived<int>[size];
for (int i = 0; i < size; i++)
{
d[i] = Derived<int>(i);
}

// delete here
}

其次,分配基类指针的动态数组,并让它们指向派生类的实际实例,即:

int main()
{
int size = SOME_LARGE_NUMBER;
Base<int>** d = new Base<int>*[size];
for (int i = 0; i < size; i++)
{
d[i] = new Derived<int>(i);
}

// delete here
}

我在任何一种情况下都将 SOME_LARGE_NUMBER 设置为 40,000,000。在第一个场景中,程序完成得很好——在第二个场景中,我得到了一个 bad_alloc 异常。我想知道这是预期的行为还是我在这里忽略了什么?如果是这样,这样做的更好方法是什么?请注意,我使用 vector<Base<int>*> 遇到了同样的问题和 boost::ptr_vector<Base<int>> .

最佳答案

好吧,如果您在一个 block 中分配,它需要 size 乘以 Derived 的大小,并且单次分配的开销很小。但是如果你单独分配,它需要 size 乘以指针的大小(4 字节),加上 size 乘以 Derivedsize(加一)乘以分配开销,至少为 8 字节。如果您靠近边缘,12 倍的 size 额外字节很可能就是是否适合内存的区别。

我不会肯定地告诉您分配器开销恰好是 8 个字节,但让它少于 2 个指针会非常复杂,而且 Microsoft 标准分配器不太可能如此复杂。

请注意,由于 std::vectorboost::ptr_vector 与您手动执行的操作完全相同,因此它们的失败方式相同。它们只是包装器,以确保在适当的时候调用 delete,仅此而已。

对于 64 位目标,所有开销都会加倍。那里的指针是 8 个字节,分配器开销通常是 2 个指针。

关于派生类的 C++ 数组与基类指向派生对象的指针数组 - 为什么分配的内存量如此不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5702184/

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