Why doesn't C++ support dynamic arrays on the stack?
在C99中,这是合法的:
1 2 3 4
| void f(size_t sz) {
char arr[sz];
// ...
} |
但是,这个动态大小的堆栈数组已经在C++中被删除,并且在C++ 11中没有看到返回。
在C++中,C++是用C语言兼容的,所以我想一定有一些很好的理由不包含这个有用的特性,对吧?
我能想到的就是:
赞成的意见
- 通过允许栈上需要的更智能的数组大小(临时缓冲区?)来节省内存。.
- 更少的"智能指针"(或者更糟的是,引入delete []的手动错误)和较慢的堆分配。
- 与C99兼容。
欺骗
- 允许人们容易地在堆栈上分配过大的数组,从而难以调试堆栈溢出。
- 对于编译器编写者来说更复杂。
那么,为什么他们在导入其他C99功能时没有包含它呢?
为了防止这被关闭为"主观的"或"不建设性的",我正在寻找来自委员会成员的报价或讨论有关此事的链接-当然是一个快速的如此全面的加分。
与其把这看作是小马对仓鼠的讨论,不如把它看作是一个历史问题,仅仅是对所考虑的利弊(如果有的话)的兴趣。
编辑:正如James McNellis在下面的评论中指出的,C++存在于C99标准化可变长度数组之前。你可能会读到我的问题:"为什么没有,他们不会添加它?".
- 它没有被"放弃",因为它从来不是C++的一部分。
- @匿名投票人:我的问题是不清楚还是没有显示研究成果?我愿意讨论它有多有用,这是我的论点:我认为这将有助于我对C++的理解。在结束投票时:我认为这是适用的:"我们希望答案通常涉及事实、参考资料或特定的专业知识"。
- @詹姆斯·麦克尼利斯:它确实从来没有掉过。但是添加了其他几个C99特性,为什么不添加动态局部数组呢?我一直在想我自己。摆脱江户11〔0〕的胡说八道是对C的一个很好的改变。
- 我认为这是适用的:这个问题可能会征求意见、辩论、辩论、投票或扩大讨论。
- 顺便说一句,在我看来,这是一个有明确答案的明确问题。这似乎不是主观的,虽然"下降"一词有点过重,也不完全准确,但我认为这只是小题大做。
- +这是一个很好的问题。也许你只需要用不同的方式来表达它,这样人们就不会对"它在C++中不存在"了。"为什么C++不允许动态堆栈数组"的问题是很好的。在添加了这么多模糊的特性之后,要想把这样一个基本特性忽略掉,必须有一个很好的客观原因。
- 我删除了"删除"一词,表示更合适的"不包括"。
- 我认为,委员会成员的报价要求将这一问题置于"不真实的问题"(无法回答)领域。也许答案只是"没人在乎它"?我怀疑是否会有这样的引用。
- @丹尼尔:不,这是个很好的问题。+ 1
- 这属于主观的"为什么没有,他们不会添加它吗?"
- 这是如何引起争论或意见?只有确凿的事实:pro和con。把它放在stackoverflow样式中:我不给出一个关于你认为正确的事实的答案,我只是想知道原因。
- 我在编辑之前的答案是"variable">secure.wikimedia.org/wikipedia/en/wiki/…长度数组是在c99中引入的。C++是基于C标准的旧版本。所以,它们不是从C++中掉出来的——它们从来都不是C++的一部分。"我正在擦除它,因为它在编辑之后不再有意义了。
- 头脑风暴:在C++中,各种大小的数组都是唯一的类型,它允许你通过引用它们来传递保留它们的大小的函数,而不是将它们衰减到指针。如果数组可以动态调整大小,这将如何工作?
- @丹尼尔A.怀特:他并没有要求任何人就为什么没有加入这个问题发表个人意见,而是要求委员会发表意见,这是一个有记录的事实,一个不公开辩论的明确事实。即使它没有被添加,因为没有人关心甚至提到它,这也是一个记录的问题,而不是主观的。
- 这就是为什么它是主观的。许多以"为什么"开头的问题都是主观的。
- 我有点惊讶,人们如此喜欢结束"为什么?""主观"问题。imho,关于stackoverflow的许多最好的问题实际上是"为什么"问题。(看这里)仅仅因为多个人对答案有多个猜测并不意味着没有正确的答案。我认为人们应该冷静一点,允许这样的问题继续下去,而不是仅仅因为他们想不出客观的答案就当场结束。:
- @丹尼尔A.怀特:为什么厨师在煮肉之前先把肉打烂?为什么地球是圆的?为什么人们仍然在汇编程序中编写代码(片段)?我们为什么存在?(开玩笑)许多"为什么"的问题都是有趣的难回答的问题。
- "夜佬"-你要求我们理解C++委员会做出的决定。
- @丹尼尔A.怀特:不,我在问他们的考虑,他们的论点,他们的利弊。
- 因此,没有正确的答案,只是扩展了讨论。
- @丹尼尔A.怀特:对不起,亲爱的丹尼尔,但现在你只是说,一般来说,历史只是主观的,我不同意。这是另一个为什么我的问题,也是主观的?stackoverflow.com/questions/4752715/…
- @丹尼尔:如果这个问题本身没有太多的元讨论,那么也许我们可以观察到它是否真的会产生关于这个主题的讨论……但现在,这些不必要的近距离投票(以及他们正在进行的讨论)比他们试图阻止的更糟糕。
- 结束问题的原因是为了保持SO的内容质量。在所有剩下的蹩脚问题中,这个问题是如何引起如此多的争议的?把它打开,它很有帮助,也很有趣。
- 我相信EDCOX1〔0〕是针对C++ Tr2提出的。
- 请移动此讨论进行聊天。
- 这不是一个糟糕的问题,因为它是主观的,它是糟糕的,因为它是重复的。-)
- 下面的评论,以及这两个答案都说明了我为什么要结束这个问题:"这个问题很可能会征求意见、辩论、辩论、投票或扩展讨论。"任何人都可以把这个问题带到meta上。这已经经历了一场公开/公开的较量。很抱歉,对于这种类型的问题,堆栈溢出不是最好的地方。
- @蒂姆·波斯特:你建议去哪个地方?我经常用so作为主题问题的边界线,这样更适合论坛,但我还没有找到一个甚至接近so质量的论坛。
- 这是stackoverflow.com/questions/1887097/variable-length-arrays-i‌&8203;n-c的副本。还有,@tim post:一半的讨论之所以发生,是因为人们出于愚蠢的原因关闭了讨论。
- @蒂姆:讨论是关于投票的元讨论,而不是关于这个问题的实际讨论。所以说这个问题引起了意见/投票/争论/不管什么都是不公平的——它与问题本身的质量无关,但是人们对他们认为对问题有好处的东西过于偏执。不过,我认为任何人把它带到meta上都没有意义,因为它显然应该作为dupe关闭(尽管我认为一些用户希望看到这是关闭的原因,包括我自己)。
- 事实:由于SIEZOF,VC++支持是不可能的,并且STD::vector已经实现了相同的特性,因此VC++在C++中是不需要的。即使在C中,该特性也会被破坏,因为您不能将这样的数组放入结构中。没有理由把它包含到C++中。
- 已投票重新打开,因此它可以作为此的副本重新关闭
我认为,这是因为C++提供了优越的解决方案:EDCOX1×1和EDCOX1×2(C++ 11);尽管后者不是动态的,但它优于原始数组。无论传递向量或数组的函数是什么,都可以知道大小。
由于C不能提供这些解决方案,C99提出了可变长度阵列(VLA)。它与常规数组有相同的问题:它在传递给函数时会衰减为指针,而您不再知道数组的大小。
正如Florian Weimer在EDCOX1 3中所说的,如果C++0x允许VLA,那么下面的代码意味着什么?
1 2
| int vla[n]; //n is known at runtime!
std::vector<decltype(vla)> v; //what does this mean? |
当矢量模板的类型参数依赖于运行时已知的n时,编译器将如何在编译时实例化它?
- 如果你-1的东西,它只是说为什么。
- @Downvoter:Please specify the reason so others and me can know why this answer is silly;and how it can be improved.
- This is a valid answer,if you disagree don't just blindly down but say in the comments.请读一下倒计时Button的工具:"这个问题不是有用的"。I disagree with that on this particular question.
- I did't-1'ed,but I don't agree"C++solutions are super":maybe they are in a lot of context.但是,在详细说明了《刑法典》的内容之后,我最近才向作者提出了唯一的敏感选择,要么是一种固定的载体,要么是固定的载体,要么是固定的载体,要么就是固定的载体。I chose vector for portability,but this left me with a not thread-safe function(which is waiting for"thread-uu local"implementation).In this case,knowing the size outside of the function was uneeded,and VLA was superior to STD::Array(BTW,I couldn't understand why STD::array was so slower than vla.
- @Rafak:You can easily avoid EDOCX1 genital 2 in standard C++as well.
- @Nawaz:yes I'm not aware of every solutions for sure,but VLA was the most straighforward one I could come with.而且,举例来说,编写一份委托书是为了解决这样一个地方化的需要。
- @Nawaz:EDOCX1 penographic 3 initialises its elements,which may income an unacceptable performance hit in some cases.The EDOCX1 original issue is a red-herring;the compiler could simply disallow it,as does the objective-C++compiler:EDOCX1 individual 5.
- Why would hep allocation be super to stack allocation?
- @Yiuin:Who said that?
- You said that C++provides superior solutions,however STD:vector is stored on the hep,STD::array isn't dynamic.I fail to see how they are superior.Lets be honest,this was added to the C standard after C++was invented,and so it just never got included.它们也很难执行,因为Stack的大多数变量通常都是指Stack+4或Stack+8或Whatever Constant。So you have to keep an offset variable for every stack variable.
- @Yiuin:C++'s EDOCX1 plication 6 welc vs C99's EDOCX1 plication 7 welcx1 which one is more safe against stack over flow?
- 第一:Stack Size Limit is Arbitrary and can be changed.Stack and hep grow towards each other,and with 64BIT address over flow is basically impossible.第二:当一个庞大的数据集被分配到一个不知道关于Stack的类型时,因为你可以打到系统的极限,有一个案例,当你可能知道你在分配的变量的范围时。第三:打破Stack的界限并不坏。你是SegfaultSo dynamic stack variables are preferable to a fixed buffer which could lead to overflow(if poorly managed)
- After thinking on this more,I think Nawaz is right in that the need was more pressing in C because it lacks variable-size data structures that may be automatically deleted,which of course could lead to memory leaks.
除了消耗更有限的资源(堆栈与堆空间),此功能在很大程度上与std::vector的功能重复。因此,在C++中,语义上并不需要它。
可以认为,堆栈分配可以提高效率(特别是面对多个线程);然而,这也可以在C++中使用自定义分配器来在堆栈或堆上构建私有内存池。这比将内存放在堆栈上更灵活,实际上,您可以创建一个自定义的分配器,足够容易地将块从堆栈上的内存缓冲区中分割出来。它与动态数组语义并不完全相同,但是定制分配器和STL容器的存在涵盖了您希望进行堆栈分配的大多数用例。
- 对此有没有讨论?我想到的一件事是,堆栈空间是自动线程本地的,这是一件非常有用的事情,因为与在许多实现上分配堆空间相比,它使分配堆栈空间的速度非常快。但我可以理解,如果考虑到这一事实,发现它不具有说服力。我只是好奇。
- @bdolan:堆栈空间是o(1)速度分配,这对于文件名(最多约256个字符)等非常有用。堆分配相对来说要慢得多,使用小字符串的应用程序通常可以通过使用前者而不是后者获得很大的好处。所以我个人不相信C++中没有"需要"。(否则,为什么编译器经常执行_alloca?
- 我不知道这是否在标准化过程中进行了讨论,但似乎是排除它的合理理由。是的,本地分配可以稍微提高效率,但是许多malloc实现无论如何都有线程本地池,对于更大的分配,构建成本无论如何都超过了分配成本。
- @Mehrdad和std::string实现通常在对象内分配小字符串…
- @真的吗?我不知道这一点——我主要使用MSVC,以前我没有观察过。请提供链接好吗?
- @ Mehrdad:"编译器为什么仍然有一个‘AloLaCa’"——因为它是在C运行库中的,它会额外地阻止它从C++使用,仅仅是为了强制编程风格?我怀疑有C++的用例,其中AlLoga和/或VLAs显得模糊有用,至少在C99中有用。但是,即使没有任何使用,也不奇怪,实现使它从C++可见。
- @Mehrdad,不是所有的实现都这样做,但有些实现是这样做的:stackoverflow.com/questions/1466073/&hellip;
- @史蒂夫:如果你怀疑这就是原因,那微软为什么还要推出_malloca和_freea来帮助开发人员在堆栈上分配内存,并调试溢出问题?当然,这是微软的额外努力,有充分的理由吗?
- @BDONLAN:您是否碰巧知道执行此操作的任何实际实现,或者只是简单地说它是一种理论可能性?(我在链接中没有找到。)
- @Mehrdad,根据本文,stlport执行以下操作:compense.sourceforge.net/compare.pdf
- @我不是说这就是原因。我的说法是,你的论点的一部分没有遵循,因为即使ALLCA被认为是无用的C++实现者,他们中的一些可能仍然将它投入,因为他们已经把它放在C周围。因此,在C++实现中的ALLACA的存在并不是你认为的冒烟枪。
- @伯顿兰:哦,哇!我试图找到源代码中执行此操作但找不到的部分。不过,在任何情况下,我可能最终会在Visual Studio中切换到stlport…这在我的一些程序中实际上很重要。谢谢你的链接!:)
- @史蒂夫:但是你的论点只适用于_alloca,而不是_malloca:那么,为什么创建了这个函数?
- @Mehrdad:在MS的情况下,由于它们一般不实现C99,并且只在抗议的情况下支持C开发,所以在我看来,它们支持VLA和所有的alloca变体,因为它们认为它们是有用的。实际上,通过保证stackoverflow上的行为,_malloca克服了VLA的主要无意义性——它比VLA更有用,因此值得付出一些努力。IIRC他们自己使用它来在ASCII和Unicode之间转换文件名等。但一般来说,C++编译器可以编译C99或接近它的东西,MS是C99 ReffSeNik的一个特例。
- @Mehrdd:The visual C++2010 EDOCX1 plographic 0 americano implementation uses the small-string最优化。
- @James:I hadn't looked at 2010,and I hadn't noticed any indication of in 2008(but I could've missed i t).但是,这是伟大的,你知道我!
- @Steve:哦,and it's worth mentioning that C@35;also supports EDOCX1 penal 1 for the same reason-and tons of people use it.You could say Microsoft i s an"exception",but IMHO if i t's an exception then i t might as well be another rule of i t s own(the fraction of people that use MS development tools i s n't exactly what I could consider neglible).