C++用string_view实现Translator类遇临时字符串返回错误求助
Translator类临时字符串翻译错误问题分析
需求背景
需要实现一个Translator类,核心要求如下:
- 默认构造创建空翻译库
- 调用
Add添加双语词对,传入的字符串可能先于Translator对象销毁 TranslateForward/TranslateBackward支持双向翻译,返回最后一次添加的对应词,无匹配则返回空字符串- 每个字符串在实例中最多存储一次,避免内存超限
原实现代码
#include <string_view> #include <string> #include <map> using namespace std; class Translator { public: void Add(string_view source, string_view target){ forward[source] = target; backward[target] = source; }; string_view TranslateForward(string_view source) const{ if(forward.count(source) == 0){ return string_view(""); } return forward.at(source); }; string_view TranslateBackward(string_view target) const{ if(backward.count(target) == 0){ return string_view(""); } return backward.at(target); }; private: map<string_view,string_view> forward; map<string_view,string_view> backward; };
问题现象
简单测试(如添加"okno"与"window"、"stol"与"table")可正常运行,但隐藏测试中出现错误:TranslateForward() returned wrong data for temporary string
错误原因
- String_view悬空问题:
string_view仅作为字符串的视图,不持有内存所有权。如果Add传入临时字符串(例如trans.Add(string("temp"), "test")),临时字符串销毁后,map中存储的string_view会指向已释放的内存,后续翻译时访问该内存会返回错误数据。 - 违反存储约束:原实现未存储实际字符串内容,无法保证字符串在
Translator生命周期内有效,同时也无法实现“每个字符串最多存储一次”的要求——重复添加相同字符串时,仅覆盖string_view,未复用已有的字符串内存。
修正方案
需要自行管理字符串存储,确保每个字符串只存储一次,同时用string_view指向这些存储的字符串,避免内存冗余和悬空问题。
修正后代码
#include <string_view> #include <string> #include <map> #include <unordered_set> using namespace std; class Translator { public: void Add(string_view source, string_view target) { // 确保源字符串被存储,返回指向存储版本的视图 const string_view stored_source = store_string(source); // 确保目标字符串被存储,返回指向存储版本的视图 const string_view stored_target = store_string(target); // 更新双向映射,最后一次添加的词对会覆盖之前的 forward_map[stored_source] = stored_target; backward_map[stored_target] = stored_source; } string_view TranslateForward(string_view source) const { auto it = forward_map.find(source); return it != forward_map.end() ? it->second : string_view{}; } string_view TranslateBackward(string_view target) const { auto it = backward_map.find(target); return it != backward_map.end() ? it->second : string_view{}; } private: // 存储所有唯一字符串,保证每个字符串仅存一次 unordered_set<string> string_store; map<string_view, string_view> forward_map; map<string_view, string_view> backward_map; // 辅助函数:将字符串存入存储池,返回指向存储版本的string_view string_view store_string(string_view sv) { // 插入字符串,若已存在则返回现有元素的迭代器 auto [it, inserted] = string_store.insert(string(sv)); // 返回指向存储字符串的视图 return string_view(*it); } };
关键改进点
- 字符串存储管理:使用
unordered_set<string>存储所有唯一字符串,严格满足“每个字符串最多存储一次”的内存约束。 - 避免悬空视图:
Add方法中先将传入的字符串存入存储池,再用指向存储版本的string_view更新映射表,确保Translator对象生命周期内视图始终有效。 - 覆盖逻辑:
map的赋值操作自动覆盖已有键值对,满足“返回最后一次添加对应词”的需求。
内容的提问来源于stack exchange,提问作者Daniil Yefimov
相关产品推荐
相关产品推荐

