按值和堆栈大小限制返回对象

Returning object by value and stacksize limit

本文关键字:返回 对象 堆栈      更新时间:2023-10-16

据我了解,在现代C++中,建议按堆栈上的值返回对象,而不是在堆上分配内存,例如make_unique<>()并返回unique_ptr。编译器将确保不会复制返回的对象值。因此,建议信任编译器来优化按值返回的返回详细信息。

但是,如果我们要遵循此建议,即使对于大型对象,理论上也可能发生堆栈溢出,对吗?我在我的 Linux 笔记本电脑上对此进行了测试:

#include <iostream>
// Allocate 40 MB (10,000,000 x 4)
#define ASIZE 10000000
struct Foo {
int a[ASIZE]; // Note: On my Linux laptop, sizeof(int) == 4
};
Foo get_foo() {
Foo a_foo;
a_foo.a[1] = 2;
return a_foo;
}
int main() {
Foo myfoo = get_foo();
std::cout << "sizeof(a) = " << sizeof(struct Foo) << "n";
std::cout << "foo1 = " << myfoo.a[1] << "n";
return 0;
}

如果ASIZE== 10,000,000,则此程序因分段错误而中止,但如果ASIZE== 1,000,000。

(我希望有一个更具描述性的错误消息,如Stackoverflow! Abort或:)的东西(。 无论如何,这与在堆栈上返回值的建议有何关系?它是否仅适用于对象的大小较小的情况?还是我错过了什么?

您始终可以从基于堆栈的容器开始,但对于堆栈上的数组,您更喜欢 std::array 或 stack_array,以避免将数组视为指针的陷阱。通常,保存所有数据的单个数组可能意味着存在数据设计问题,因此在切换到堆对象之前,我会先考虑一下,而无需三思而后行。

如果堆栈大小确实是问题所在,则可以使用基于堆的标准库容器(例如vectorlist等(。这些解决了堆栈溢出问题并支持移动语义,因此使用引用和按值复制仍然应该优先于使用智能指针。