此示例中引用静态变量的引用返回是否安全?

时间:2015-07-22 08:14:40

标签: c++

我遇到了下面的代码示例,我有点困惑。像这样返回对静态引用变量的引用是否安全?

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;
}

如果安全,有人可以告诉我原因吗?如果它不安全,编译器为什么不抱怨呢?

2 个答案:

答案 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在发表评论之前询问真实的代码是正确的,我回去阅读真实的代码。