Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.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++ - Fatal编程技术网

C++ 条件堆栈变量

C++ 条件堆栈变量,c++,C++,给定以下函数,是否会在堆栈上声明每个局部变量 std::string reallyCoolFunction(unsigned int a) { if( a < 20 ) { std::string result1 = "This function is really cool"; return result1; } if( a >=20 && a <= 40 ) { std::string resu

给定以下函数,是否会在堆栈上声明每个局部变量

std::string reallyCoolFunction(unsigned int a)
{
   if( a < 20 ) 
   {
     std::string result1 = "This function is really cool";
     return result1;
   }

   if( a >=20 && a <= 40 )
   {
     std::string result2 = "This function is kind of cool";
     return result2;
   }

   if( a > 40 )
   {
     std::string result3 = "This function is moderately cool";
     return result3;
   }

 std::string result4 = "This function really isn't that cool"; 
 return result4; // remove warning

}
std::string reallyCoolFunction(无符号int a)
{
如果(a<20)
{
std::string result1=“这个函数真的很酷”;
返回结果1;
}
如果(a>=20&&a 40)
{
std::string result3=“此函数相当酷”;
返回结果3;
}
std::string result4=“这个函数真的没有那么酷”;
返回结果4;//删除警告
}

在这种情况下,实际上只需要一个
std::string
,是在堆栈上分配所有4个,还是只分配1个?

在大多数编译器上,只分配一个字符串。请记住,
std::string
使用动态内存,因此其大部分内容仍将在堆上分配。

取决于编译器。
如果编译器足够智能,可以确定只需要一个字符串,那么它将只为一个字符串发出代码

您的编译器足够智能吗?

最简单的方法是检查生成的汇编代码

是全部4个都分配到堆栈上,还是只分配1个?


无论是1个字符串还是4个字符串,字符串对象都位于函数的本地堆栈上,但字符串的内存分配在freestore中。

这取决于编译器:由于自动变量在下一个变量进入作用域之前超出作用域,编译器可以重新使用它们的内存。请记住,“堆栈”变量实际上是根据C++规范自动存储的变量,因此它们可能根本不在堆栈上。

< P>编译器允许在这种情况下创建4, 1, 2个或3个变量。但据我所知,大多数编译器只会创建一个或两个,因为result4在函数的整个范围内

当然,如果您做了“正确”的事情,编译器可能会感到困惑,并且做的事情比它绝对需要的要多,因此在关键功能中依赖这一点并不是一件特别好的事情

编辑:我应该补充一点,std::string的构造函数只应该在对象实际“使用”时运行,因此您可以使用堆栈空间,但它不应该调用构造函数。如果您这样做,这一点很重要:

void func()
{
    if (something)
    {
        Lock myLock(&global_lock_object);   // Constructor locks global_lock_object
        ... do stuff that needs global_lock_object locked ... 
        // end of scope runs destructor of Lock that unlocks global_lock_object. 
    }
    ... more code that takes a long time to execute but doesn't need lock. ...
}

现在,如果
Lock
的构造函数“太早”执行,并在同一范围内销毁[而且应该是对称的],那么锁将在函数的整个期间保持,这是错误的

简短回答:看看汇编程序

详细回答:编译器可能会应用静态检查来确定他是否需要全部4个变量,还是只需要部分变量。有些编译器可能会在调试模式下分配4个不同的变量,有些可能不会。在发布模式下,一些优化器可能会看到前3个都在各自的范围内,因此可以放在相同的位置。因此,这些编译器可以在堆栈上为两个字符串变量保留空间。只需要再进行一点分析,就可以看到第四个变量在任何情况下都不会与前三个变量共存,因此一些优化器可能会将剩余的两个变量放在同一个位置


但是您的编译器是否这样做,以及他是否在稍微复杂的情况下仍然这样做,只有在您分析输出时才能确定。

最有可能的是0或者1(发行版),当然还有4(调试版)

这称为RVO:返回值优化

编译器实际上可以完全删除副本,并直接在调用者提供的插槽中构建
std::string
。这是特定于ABI的,因为所有优化仅在满足许多条件时才适用;在你的情况下,它很可能适用


如果您想检查,您可以尝试在编译器的翻译/优化管道的不同阶段仔细阅读编译器的输出;这可能很难,但取决于您的工具链。

我相信我的回答中有一个重要的部分您忘了提及,即大多数字符串不会分配到堆栈上。我认为这是值得的mentioning@IvayloStrandjev绝对正确-我投票支持你的答案正是因为这个原因:)自动存储保证了堆栈行为。这就是“堆栈”所指的。“实际上”实际上是一个相当愚蠢的词。一个自动变量只能通过在“好像”规则下进行优化来避免在堆栈上分配,然后就好像它是在堆栈上分配的一样,因此对此没有太大意义。字符串可能使用动态内存,但不一定。例如,请参阅MSVC标准库中的小字符串优化。无论是1个字符串还是4个字符串,字符串对象都位于函数的本地堆栈上,但字符串的内存分配在freestore中。=>SSO:短字符串优化(在Dirkumware和libc++中实现)@MatthieuM.:True&agree。谢谢你的更正。更准确地说,这是一个实现细节。该标准并不要求在何处进行存储,它只要求执行
std::string
必须遵守的某些可观察行为。是的,C++03和C++11之间的一个显著变化是gcc的优化(写时复制)由于新的限制,不再可能了。@MatthieuM.:这很有趣。你能(如果可能的话)给我提供一些参考资料,让我在这方面做更多的探索。参见