Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 把它放在堆栈上还是放在堆上?_C++_Stack_Heap_Cpu Cache - Fatal编程技术网

C++ 把它放在堆栈上还是放在堆上?

C++ 把它放在堆栈上还是放在堆上?,c++,stack,heap,cpu-cache,C++,Stack,Heap,Cpu Cache,函数使用本地缓冲区准备有限大小的数据块并将其传递给另一个函数,如下所示: void foo() { char buffer[MAX_SIZE]; size_t size = write_fancy_things(buffer); bar(buffer, size); } 但是,根据MAX_SIZE的值,您可能会担心占用太多堆栈,并使用类似于以下示例的内容替换代码(但希望更加关注内存管理): 在一般情况下,这两个函数的行为应该相同。然而,在第一个示例中,如果MAX_SIZE太大,我们

函数使用本地缓冲区准备有限大小的数据块并将其传递给另一个函数,如下所示:

void foo()
{
  char buffer[MAX_SIZE];
  size_t size = write_fancy_things(buffer);
  bar(buffer, size);
}
但是,根据
MAX_SIZE
的值,您可能会担心占用太多堆栈,并使用类似于以下示例的内容替换代码(但希望更加关注内存管理):

在一般情况下,这两个函数的行为应该相同。然而,在第一个示例中,如果
MAX_SIZE
太大,我们更有可能达到堆栈限制。如果您知道函数在哪里使用,那么使用大值可能很好,但有时您不知道

在第二个示例中,我们处理的是额外的间接寻址,缓冲区更容易出现CPU缓存未命中,如果
foo
位于低延迟关键路径上,则可能出现这种情况,并且我们预计在大多数情况下,准备缓冲区的成本非常低

你认为什么尺寸太大而不能堆叠?在堆栈上放置大块数据,但只使用其中的一小部分,是否也会受到惩罚


EDIT:这个
write\u fancy\u things
只是一个同义词,意思是“我正在向缓冲区写入一些数据,大小在1到最大字节之间”。您可以将第二个
foo
示例视为类方法,将静态指针视为构造函数中分配的类成员。我可能只是把事情简单化了,但我不想引入比需要更复杂的内容,并将重点放在堆栈上。

将数据放在堆栈上不会有任何损失,因为您只是在减少堆栈指针

堆栈大小可以使用操作系统实用程序修改,因此我不会担心高达1MB的大容量


但我会担心递归调用。它们可能根本不会发生,因为它们会炸毁堆栈。

这两者甚至根本不相同。第二个对所有调用使用相同的缓冲区,第一个使用新的缓冲区,这意味着第二个不是线程安全的


这种风格太可怕了。如果write_fancy_things只使用X多个字节,而X在编译时是未知的,那么动态分配X字节。不要在堆栈上分配希望的最大大小,也不要使用希望的最大大小更大的静态缓冲区。使用正确类型的向量,将其大小调整为适当的大小,然后使用该缓冲区。

如果您开始担心大小,请选择堆,否则选择堆栈


考虑所有因素。

如果帧边界有冲突问题(因为最大大小太大),则转换为std::vector

void foo()
{
  std::vector<char> buffer(MAX_SIZE);
  size_t size = write_fancy_things(&buffer[0]);
  bar(&buffer[0], size);
}
void foo()
{
标准::向量缓冲区(最大大小);
size\u t size=write\u fancy\u things(&buffer[0]);
条(&缓冲区[0],大小);
}

坦率地说,您的版本是非初学者。

您确定您的
正在使用“堆”吗?它正在使用堆。非常在某种程度上,堆分配几乎没有任何优势。@Tomalak现在我不是;如果不是堆比什么?@bdonlan这就是全部要点,唯一的优点是我没有使用堆栈空间,我更喜欢使用作为缓冲区的局部变量。所以我开始放置
char buffer[10000…
,后面的每一个零都会让我担心。@tg:不要称它为堆。称它为动态分配内存。它符合它的实际类型(自动/静态/动态/线程).+1.使用
静态
指针动态分配静态大小的缓冲区是没有任何用处的。好吧,也许我在伪代码中过于简化了…write_fancy_事情就要说了,我要写一些介于1和MAX_大小字节之间的内容,所有值都有可能,所有值都会被命中,但主要是一个小值会被命中使用。线程不安全很好,但这里的情况确实不是这样。如果主要是一个小的分配,为什么不让
写一些花哨的东西
进行分配?最大大小有多大?虽然这可能是最安全和灵活的方法,但速度很慢。正如我指出的,foo位于一条低延迟的关键路径上d堆栈缓冲区工作得很好。但是,由于我的代码是库的一部分,其他人会使用它,所以在使用(比如说)单个调用中的100KB堆栈时,它不是有点滥用吗?@tg:一个选项是将问题推到楼上——记录库调用需要100KB缓冲区,如果用户愿意,让用户提供,然后d动态地分配它。这样,任何可以通过在堆栈上传递缓冲区来衡量其应用程序整体性能改进的用户都会感到高兴。如果实际使用的空间量是不可预测的,以
MAX_SIZE
为界,但通常要小得多,那么您可能不想使用
vector
,因为它zero非常缓慢地初始化缓冲区,而不是
作用域数组
或类似。
void foo()
{
  std::vector<char> buffer(MAX_SIZE);
  size_t size = write_fancy_things(&buffer[0]);
  bar(&buffer[0], size);
}