当前位置:  开发笔记 > 编程语言 > 正文

有没有办法以编程方式确定C++数组的大小?如果没有,为什么?

如何解决《有没有办法以编程方式确定C++数组的大小?如果没有,为什么?》经验,为你挑选了4个好方法。

这个问题的灵感来自一个类似的问题:delete []"如何"知道操作数数组的大小?

我的问题有点不同: 有没有办法以编程方式确定C++数组的大小?如果没有,为什么? 我看到的每个接受数组的函数也需要一个整数参数来赋予它大小.但正如链接问题指出的那样,delete[]必须知道要释放的内存大小.

考虑这个C++代码:

int* arr = new int[256];
printf("Size of arr: %d\n", sizeof(arr));

这打印" Size of arr: 4",这只是指针的大小.有一些打印256的函数会很好,但我不认为C++中存在一个函数.(同样,问题的一部分是为什么它不存在.)

澄清:我知道如果我在堆栈上声明数组而不是堆(即" int arr[256];"),则sizeof运算符将返回1024(数组长度*sizeof(int)).



1> Dima..:

delete []确实知道分配的大小.但是,该知识驻留在运行时或操作系统的内存管理器中,这意味着编译期间编译器无法使用它.并且sizeof()它不是一个真正的函数,它实际上被编译器评估为常量,这是动态分配的数组无法做到的,它的大小在编译期间是未知的.

另外,请考虑以下示例:

int *arr = new int[256];
int *p = &arr[100];
printf("Size: %d\n", sizeof(p));

编译器如何知道它的大小p是多少?问题的根源是C和C++中的数组不是第一类对象.它们衰减为指针,并且编译器或程序本身无法知道指针是指向由new一个对象分配的内存块的开头,还是指向一个块中间的某个位置.分配的内存new.

其中一个原因是C和C++将内存管理留给程序员和操作系统,这也是他们没有垃圾收集的原因.实现new并且delete不是C++标准的一部分,因为C++旨在用于各种平台,这些平台可以以非常不同的方式管理它们的内存.如果您为最新的Intel CPU上运行的Windows框编写文字处理器,可以让C++跟踪所有已分配的数组及其大小,但是当您编写运行的嵌入式系统时,这可能是完全不可行的.一个DSP.


迪马,绝对是阵列.数组与指针不同.可悲的是,许多老师对此感到困惑,并告诉他们的学生他们是"正义"的指针.不,他们不是.你怎么解释这个:char const**s =&"bar"; 不编译?[...]
C++中有绝对的数组.你怎么解释为什么用这个"char x [4]; size_t sz = sizeof(x);" 'sz'将被分配4?
litb,char const**s =&"bar"的原因; 不编译是"bar"是常量而不是左值,所以你不能取它的地址.它与int*p =&5相同; 这也不会编译.
`void foo(int*a);`接受一个指针,`void foo(int(&a)[5]);`接受一个数组.数组名称衰减为指针,这很糟糕,但它并不意味着数组和指针是相同的.
很明显,但几乎一切都是错的.已经有一种情况,sizeof是运行时而不是编译时,Arrays _do_存在,并且有一些方法可以让实现知道所有数组的大小.甚至DSP _must_保留分配的大小信息.
@Dima:你错了.数组确实存在,而"x"`*是左值.数组和指针衰减非常糟糕,但它们*是*不同的东西.函数`void foo(int*a)`接受指向单个整数的指针.这个指针可能指向数组元素的事实,无论是第一个通过指针衰减还是任何其他方式,都是无关紧要的.
任何看到这个的人都需要投票.这里有很多错误.这是一个普遍的误解*
凯文,x并不是一个真正的数组.它是指向一块内存的指针,它恰好位于堆栈中.并且因为它是在堆栈上静态分配的,所以编译器知道它的大小.如果将x传递给函数,它将不知道它的大小.C或C++中的数组不是第一类对象.
@Dima:当你说"一流物体"时,你究竟是什么意思?当你声明`int a [4];`时会产生一个连续的4字节内存块.这有什么不足以告诉你这不是一个数组?我不打算继续努力,我想弄清楚.

2> James Curran..:

不,在标准C++中没有办法做到这一点.

没有什么理由不是我所知道的.可能,大小被认为是一个实现细节,最好不要暴露.请注意,当您说malloc(1000)时,无法保证返回的块是1000字节 - 只有它至少为 1000字节.最有可能的是大约1020(1K减去4个字节的开销).在这种情况下,"1020"大小是运行时库记住的重要大小.当然,这会在实现之间发生变化.

这就是为什么标准委员会添加了std:vector <>,它确实跟踪它的确切大小.


需要注意的一点是new []确实存储了所请求项的数量,以便为数组调用正确数量的构造函数和析构函数.存储的位置再次是特定于实现的.不包括获得它的方法的理由超出了我的想法.
啊哈......当然.int*无法知道它指向的数组是新数组还是本地数组或数组中间的某个点.
@Herms:std :: string [10]绝对不是原始内存,但它是一个数组.

3> João Augusto..:

那么实际上有一种方法可以确定大小,但它不是"安全的",并且与编译器和编译器不同...... 因此它根本不应该被使用.

当你这样做:int*arr = new int [256];

256是无关紧要的,你会得到256*sizeof(int)假设这个情况1024,这个值可能存储在(arr - 4)

那么给你一些"项目"

int*p_iToSize = arr - 4;

printf("项目数%d",*p_iToSize/sizeof(int));

对于每个malloc,new,无论你收到的连续内存块之前的什么,都会分配一个空间,其中包含有关你给出的内存块的一些信息.


尽管如此,这实际上回答了这个问题.

4> Doug T...:

处理此问题的常用方法是使用向量

int main()
{
   std::vector v(256);
   printf("size of v is %i capacity is %i\n", sizeof(int) * v.size(), sizeof(int) * v.capacity());
}

或预定义大小

const int arrSize = 256;
int main()
{
    int array[arrSize];
    printf("Size of array is %i", sizeof(int) * arrSize);
}

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有