如何在没有编译器警告的情况下返回对空字符串的 const 引用?
Posted
技术标签:
【中文标题】如何在没有编译器警告的情况下返回对空字符串的 const 引用?【英文标题】:How can I return a const reference to an empty string without a compiler warning? 【发布时间】:2015-05-14 13:56:40 【问题描述】:我有一个 std::unordered_map<int, std::string>
和一个函数 GetString(int key)
,它接受一个 int 键并从此映射返回一个字符串值。
当在地图中找不到键时,我必须返回一个空字符串。
#include <iostream>
#include <string>
#include <unordered_map>
std::unordered_map<int, std::string> map
5, "somelongstring"
;
const std::string& GetString(int key)
auto iterator = map.find(key);
if (iterator == map.end())
return "";
return iterator->second;
int main()
std::cout << GetString(1) << std::endl;
问题是编译器给了我这个警告
warning C4172: returning address of local variable or temporary
(使用 MS Visual Studio 2013)或
warning: returning reference to temporary [-Wreturn-local-addr]
(使用 g++ 4.9.2)
我发现摆脱这种情况的一种方法是在顶部声明 static const std::string
并返回它而不是空字符串文字
static const std::string Empty = "";
const std::string& GetString(int key)
auto iterator = map.find(key);
if (iterator == map.end())
return Empty;
return iterator->second;
但是定义一个空字符串字面量似乎不是很干净。有没有一种巧妙的方法来做到这一点?
更新:我的地图在启动期间被初始化一次,然后从多个线程同时读取(使用GetString
)。使用函数静态空字符串不起作用,因为函数静态变量在 Visual Studio 的编译器下没有以线程安全的方式初始化。
【问题讨论】:
我认为std::unordered_map
与您的问题没有任何关系,真的。
const 字符串在函数中可以是静态的,而不是全局的。
我认为没有更好的解决方案。您需要一个 string
实例,该实例在您返回引用时仍然有效,或者您自己返回一个 string
实例(不是引用),但这可能效率低下。
@einpoklum 文字是const char[1]
类型,要返回对std::string
的引用,会创建一个临时文件,但您不能(合法)返回对临时文件的引用。跨度>
@einpoklum 字面量不是 std::string
。这是一个C字符串。要从此函数返回它,必须将其转换为std::string
,在此过程中创建一个临时对象。返回对该临时对象的引用,就像它超出范围并被销毁一样。
【参考方案1】:
警告消息明确说明了问题所在:您正在返回一个局部变量 (""
") 的地址,该变量将在函数返回后从堆栈中释放。返回 std::string
会很好,因为您将在函数局部变量之外构造一个新字符串,但是当您返回 std::string&
时,您确实使用了局部变量。
但是当您返回一个静态值时,只需将其设为静态即可:
const std::string& GetString(int key)
static const string empty = "";
auto iterator = map.find(key);
if (iterator == map.end())
return empty;
return iterator->second;
【讨论】:
Afaik,函数静态变量在 Visual Studio 的编译器下没有以线程安全的方式初始化,尽管 c++ 11 标准要求这样做 @tcb 你是对的。通过您的编辑,我现在认为,除非您可以确保该函数至少会被调用一次(例如在地图初始化之后),否则 global 静态常量是最好的方法。 C++11 "magic statics" 现在也被 Visual Studio 2015 编译器支持 - blogs.msdn.microsoft.com/vcblog/2015/06/19/…【参考方案2】:我会将返回类型更改为std::string
(因此返回空字符串是可以的)或std::string *
(返回nullptr
表示未找到)。
否则编译器是对的:你不能返回对即将被销毁的本地对象的引用
【讨论】:
返回 std::string 不是一个选项,因为我的地图包含巨大的字符串,我不想制作任何副本。我正在考虑返回一个指针,但如果可能的话,我想避免使用指针。 如果您返回一个指针,那么也可以考虑将其设为const std::string*
,因为 OP 也返回了 const std::string&
。另外,它改变了调用者的界面,所以我不太喜欢这个主意。以上是关于如何在没有编译器警告的情况下返回对空字符串的 const 引用?的主要内容,如果未能解决你的问题,请参考以下文章
在 PHP 5.3 中,如何在没有严格警告的情况下在一行中获取单个元素数组中的值