[英]Why would you use the stack if there is a possibility of stack overflow
假设我有一个代表我的应用程序的类:(很抱歉,没有同时显示h和cpp,但这是为了简洁)
class App
{
App()
{
window( new Window() );
window->Height( 400 );
window->Width( 400 );
window->Title( "Bob" );
}
unique_ptr<Window> window;
// ... Possibly more variables
}
class Window
{
public:
// Get
int Height(){ ... };
int Width(){ ... };
string Title(){ ... };
// Set
void Height( int height ){ ... };
void Width( int width ){ ... };
void Title( string title ){ ... };
private:
int height;
int width;
string title;
// ... Possibly more variables
}
App app;
int main()
{
}
Window
类中的所有int
和string
类型都在堆栈上声明。 在某些时候,如果我继续在这些类中的堆栈上声明一些东西,我将最终导致堆栈溢出……对吗?
所以我的问题是 ...为什么你要在堆栈上声明东西? 我们不应该只是这样做吗?
// ...
App()
{
window( new Window() );
window->Height( unique_ptr<int>( new int( 400 ) ) );
window->Width( unique_ptr<int>( new int( 400 ) ));
window->Title( unique_ptr<string>( new string( "Bob" ) ) );
}
// ...
private:
unique_ptr<int> height;
unique_ptr<int> width;
unique_ptr<string> title;
...
区别在于,现在在堆上声明了整数和字符串的内存。
Why would you ever want to declare stuff on the stack?
我能想到的2个原因:
性能:堆栈非常快。 我记得在某处听到过这种声音,但是提高性能的最好方法是避免绊倒。
复杂性:使用动态内存会带来更多的复杂性,因为您必须考虑内存管理。 使用堆栈使它比使用堆更简单。 使用动态内存会增加程序的复杂性。
即使将window声明为unique_ptr<Window> window
窗口, unique_ptr<Window> window
在堆栈上声明某些内容。 在这种情况下, unique_ptr<Window>
的实例。 在堆栈上声明int和其他小的原语或结构是很好的,因为即使在堆上声明它们,也需要在堆栈上声明指向它们的指针。 您将始终需要在堆中保留指向堆中位置的指针,因此,如果您的数据类型小于指针(或接近相同大小),则将其保存在堆栈上的效率甚至比将其保持在堆栈上的效率更高。堆。 这是因为访问堆栈要比堆快,并且在内存方面,当存储在堆上时,必须存储两个对象(指针和对象本身),而存储在栈上则只能存储一个对象。
以std::string
为例。 它可能在内部持有一个指向堆上原始数据存储位置的指针。 因此,在堆栈上,您要持有一个指针,在堆栈上,则要保留原始数据(字符串字面量有所不同,一般思路仍然存在)。
通常,除非将int作为数组的地址,否则将int存储在unique_ptr
几乎没有意义。 如果仅将其声明为原始int,则效率更高且易于维护。
您过早担心优化堆栈使用情况。
您指出了C ++。
对于Linux上的C ++,Ubuntu 12.04和15.04的默认堆栈大小为8 MB。
sizeof()的高度和宽度分别为4个字节。
如果您在Ubuntu 15.04上使用std :: string和gcc 4.9,则sizeof(an_empty_std_string_object)为8个字节(在堆栈上)
另外,sizeof(a_100_char_string_object)仅8个字节。 我猜想std :: string是动态内存的简单包装,但是我从未检查过。
因此,一个8 MB的堆栈将容纳16个字节对象中的10 ^ 6个以上。 也许您可以使用递归来填充此堆栈。
想象一下,您将对象的所有16个字节移到堆中(即,将对象新添加到堆中)
您仍将在堆栈上使用8字节(在64字节linux上)指向您的对象。
我没有看过智能指针有多大,但是可能不确定为16字节。
也许您担心到足以将每个对象放入向量中。 空向量为24个字节,一个1000元素向量也是如此,一百万个元素向量也是如此,...
无论如何,如果您接近堆栈限制(这是可行的,我已经使用递归算法完成了此操作),那么在Linux中,您可以更改堆栈大小...我尝试了1 GB的堆栈...只是为了看看有多大递归程序将得到。 没那么远。 (抱歉,我没有完成该实验。)
Window类中的所有int和string类型都在堆栈上声明。
不,不是。 您的int和string类型被声明为类实例的数据属性。 如果您的类实例在堆上实例化(即使用new),则该数据将在堆中而不是堆栈中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.