我遇到了下面的代码示例,我有点困惑。像这样返回对静态引用变量的引用是否安全?
static const defValue = 0;
const std::string& f(const int n)
{
static std::string& str = std::to_string(defValue);
...
// str might be changed here
return str;
}
如果安全,有人可以告诉我原因吗?如果它不安全,编译器为什么不抱怨呢?
答案 0 :(得分:0)
该示例无效,因为它引用了来自std::to_string
的返回值,这是一个临时值 - 通过使其成为引用,它“保持活动”直到范围结束引用(假设它完全编译 - 标准C ++不允许这个构造),但除此之外,它仍然是一个局部变量,因此返回str
将返回对局部变量的引用。
如果您将其更改为:
static std::string str = std::to_string(defValue);
所以str
本身是一个静态std::string
对象,然后将存储to_string
结果的副本[使用RVO来消除实际副本,因此没有真正的开销]。然后返回对str
的引用是安全且正确的[请注意f
的所有来电者将获得完全相同的str
[虽然它以const
的形式返回,但从技术上讲有效将其强制转换为非const并在这种情况下修改值,因为原始引用是非const对象]
答案 1 :(得分:0)
是的,通过查看函数的第一行,这是一段危险的代码。这是我的直觉,我发布了一个问题,要求确认我的直觉。在发布问题之后,我仔细阅读了真实的代码,发现它可能不是我的想法。
函数的第一行用作引用变量声明的初始化,必须用引用变量声明的东西初始化。 C ++不允许在没有初始化的情况下声明引用变量。在“str可能会在这里更改”,它会执行类似下面的操作(同样不是真正的代码):
const std::string& Cls::Mtd(const int n)
{
static std::string& last = std::to_string(defValue);
...
// str might be changed here
auto itr = stringMap.find[n];
if (stringMap.end() == itr)
{
stringMap.insert(std::pair<int, std::string>(n, last));
}
last = stringMap[n];
return last;
}
这是我用来解释实际代码粗略做什么的一段伪代码。在实际代码中,stringMap是堆分配的复杂数据结构。 所以我跳得太快,并发布了我问的问题。 Alf在发表评论之前询问真实的代码是正确的,我回去阅读真实的代码。