2012-09-27 42 views
20

为什么无法获得以这种方式分配的缓冲区的长度。查找动态分配数组的大小

AType * pArr = new AType[nVariable]; 

当同一阵列被释放

delete [] pArr; 

运行时必须知道有多少解除分配。在删除数组之前是否有任何方法可以访问该长度。如果不是,为什么不提供这样的API来获取长度?

+1

优秀问题1 –

+0

最佳的方法是使用,'的std ::矢量帕尔(nVariable);'。这在内部使用动态分配进行分配,并且'.size()'总是方便的。 – iammilind

+1

[这个C++常见问题。(http://www.parashift.com/c++-faq-lite/num-elems-in-new-array.html) – jrok

回答

4

是否有任何方法可以在删除数组之前访问该长度?

不,没有办法确定。
该标准不要求实现记住并通过new提供请求的元素数的细节。
实现可能只是在分配的内存块末尾插入特定的位模式,而不是记住元素的数量,并且可能在释放内存的同时简单地查找模式。
简而言之,它完全是一个无限细节。


在一个侧面说明,有2个选项,切实解决这个问题:

  1. 你可以简单的使用std::vector提供您喜欢size()
  2. 你可以简单的成员函数自己做记账。

newATLEAST分配,你要求足够的内存一样多。
您已经知道您要求多少内存,以便您可以轻松计算长度。您可以使用sizeof找到每件商品的尺寸。

Total memory requested/Memory required for 1 item = No of Items 
+0

这downovte是因为......? –

+3

我没有降低你的评价,但我认为问题在于他问为什么这个标准没有提供这个标准,而你说这是因为标准说的那样。他要求的是一个理由,而不是为了解决具体问题。 – akappa

+0

@akappa:我的回答指出了理由,实现可以有效/更好地记录分配的内存,因此标准不会强制实现以特定方式执行。实际上,答案甚至说出这样一种方式。既然你说这不是理由,请启发我如何/为什么你认为这不是一个理由? –

5

运行时知道分配了多少。然而,这些细节是编译器特定的,所以你没有任何跨平台的方式来处理它。

如果你想相同的功能,并能够跟踪大小,你可以按如下方式使用一个std ::向量:

std::vector<AType> pArr(nVariable); 

这与使用RAII以及附加优势。

+0

我同意这个实现是编译器特定的。但是阻止该标准要求C++供应商公开如下所示的API。 size_t array_sizeof(void const * pHead); – Ram

+0

@Ram:我不知道什么时候停止标准,要求尽可能多的运行时间允许它。可能有某种方法可以实现不能完成的分配,这就是不强迫它被暴露的原因。然而,我不能想到,虽然你不能做到这一点的分配模式... – Goz

+0

@Ram:就个人而言,我总是使用矢量而不是动态分配RAII的好处,复制语义和大小跟踪。 – Goz

2

不,不是。至少不是平台无关的,定义的方式。

尽管大多数实现会在实际数组之前存储动态分配数组的大小。

+3

真的。我见过的那些没有。 –

+0

@JamesKanze MSVS肯定会。 –

+0

我刚用VC10试了一下。如果我做'new char [10]',则返回的指针前面的'size_t'包含'917978'。 (使用g ++时,它包含'17',它实际上可能与分配的内存量有关,因为对齐考虑需要四舍五入到8的下一个倍数。) –

3

delete运营商不需要知道大小来释放分配的内存,就像free系统调用不需要。这是因为这个问题留给操作系统而不是编译器运行时系统。

+1

不是真的,删除操作和免费库函数需要知道这一点。我认为许多实现不会将堆分配的内存返回给操作系统,而是重用它,即使它们返回内存,在释放/删除调用和返回内存的系统调用之间也没有1:1映射(这是因为操作系统通常不会允许您以小块返回内存,但会以页面大小的倍数)。 –

+1

至少对于非POD数据类型,运行时必须知道它,因为它必须调用dtors。对于POD数据类型,可以肯定地说C++ RTS可能会或可能不知道已经分配了多少空间,因为裸内存处理不符合标准。 – akappa

3

运行时必须解除分配,因为它分配相同量,并且它的这个 跟踪以某种方式(通常非常间接地)。但 有一个从分配给 元素个数量越来越没有可靠的方法:分配不能少于 元素乘以每个元素的数量大小的量,但它往往会更多。例如,对齐方面的考虑意味着new char[5]new char[8]将经常分配相同数量的存储器,并且存在各种分配策略,这些分配策略可能会导致明显需要分配明显更多的存储器内存 。

0

为什么不一点额外的信息是这样的:

template <typename T> class AType 
{ 
public: 

    AType(size_t s) : data(0) 
    { 
     a_size = s; 
     data = new T[s]; 
    } 
    ~AType() { 
     if (data != nullptr) 
      delete [] data; 
    } 

    size_t getSize() const 
    { 
     return a_size * sizeof(T); 
    } 

private: 
    size_t a_size; 
    T* data; 
};