声明指针或堆栈变量

declaring a pointer or a stack variable

本文关键字:变量 堆栈 指针 声明      更新时间:2023-10-16

假设我们有以下情况:

  • 如果是早晨心情好,否则心情不好
  • 打印心情

可以写成:

std::string mode; //this cost us calling the constructor of std::string
if(time==Morning){ // a real code should be here
   mood="Good"//re assign the string
}
else{
   mood="bad"//re assign the string
}
std::cout << mood;

假设它不是std::string,它是一个非常大的对象。声明"mode"并无缘无故地调用构造函数不是太奢侈了吗?使用原始指针是解决方案吗?这里的最佳实践是什么?由于

可以使用三元操作符初始化字符串。

std::string mode = (time == Morning ? "Good" : "Bad")

正如MSalters在评论中指出的,这实际上仍然是两个结构(构造函数+副本),但它应该得到编译器的优化。你可以用

直接初始化字符串
std::string mode { (time == Morning ? "Good" : "Bad") };

我会考虑将逻辑放入一个单独的函数中。这有助于保持函数小而简单。

std::string moodAtTime(Time time)
{
    if(time==Morning)
    { // a real code should be here
        return "Good";
    }
    else
    {
        return "bad";
    }
}
std::string mood = moodAtTime(t);

这减少了函数的长度,并将代码分割成执行简单问题的小单元。

如果它只是用于初始化,您可以使用lambda来完成它,而不需要命名函数:

std::string mood = [](Time t)
{
    if(t==Morning)
    { 
        return "Good";
    }
    else
    {
        return "bad";
    }
}(now);

如果您多次进入特定的作用域分配,则成本会变得很高,是的,它可能会变得非常昂贵(取决于作用域内发生的事情)。

解决方案是保留一个全局变量,或者更广泛地使用一个这样的对象池(对象池/内存被广泛用于这种目的,特别是在小对象和非常小的对象的情况下)。

那么,用代码

来解释
 // scope that is entered allot, like 100k times per second
 {
   std::string temp;
   ...
   // magic happens
   ...
 }

快速解决方案

 {
    static std::string g_uniqueNamed_temp_string;
    ...
    // magic happens
    ...
 }

优雅的解决方案

编辑:切换到原始指针以避免复制

 {
   std::string* tempString = StringPool::GetAPreallocatedString();
   ...
   // magic happens
   ...
 }

您可以使用alloca:

#include <iostream>
#include <sstream>
using namespace std::literals;
int main() {
    void *mem = alloca(sizeof(std::string)); //Allocates memory on stack; no initialization
    std::string *mood;
    if(true){ // a real code should be here
        mood = new (mem) std::string("Good");//re assign the string
    }
    else{
        mood=new (mem) std::string("Bad");//re assign the string
    }
    std::cout << *mood;
    return 0;
}