从运算符[]返回对映射的char*的引用
returning a reference to mapped char* from operator[]
我有一个数据结构:
#include <map>
struct array{
map<const char*, char*> data;
//constructor
array(const char* key, char* value = ""){
data.insert(pair<const char*, char*>(key, value));
}
//overloaded operator[] seems to be my problem
char* operator[](const char* key) { return (char*)data[key]; }
};
现在,在没有使分配operator=
过载的情况下,我进行了试驾它是这样的:
array var("first", "second");
var["third"] = "fourth"; //and my compiler (gcc) is angry about this
现在,我的编译器返回了以下错误:
函数.cpp:13:18:error:赋值的左操作数需要左值
问题:我有什么不明白的地方吗?我该怎么办从CCD_ 3返回CCD_,以便CCD_ 4正常工作?请注意,我不想用c++的字符串类型来做这件事。严格地说是CCD_ 5。
我有什么不明白的地方吗?
您正在按值返回指针。这意味着调用者将收到指针的副本。调用方不能使用映射中指针的副本来更改映射中的指针。
如何从运算符[]返回map::data["key"]的地址,使var["third"]="fourth";工作正常吗?
返回对它的引用:
char*& operator[](const char* key) { /* ... */ }
为了做到这一点,你需要去掉多余的演员阵容:
return data[key];
程序中的另一个问题是,您在映射中存储了非常量char*
,但您用字符串文字初始化了这些指针,即const
。这种转换在c++11中是非法的,这意味着你的程序格式不正确。甚至在c++11之前,由于标准c++已经存在,这种转换就已经被弃用了。
这样做的危险在于,您可能会意外地通过非常量指针修改常量字符串,这将导致未定义的行为。
解决方案:如果不需要修改字符串内容,请在映射中使用const char*
指针。如果需要修改,则改为指向从字符串文字中复制的单独分配的char
数组。实现后者的最简单方法是使用std::string
作为值类型,但如果您不想这样做,那么您可以自己管理数组。
程序中的第三个问题是,您似乎认为var["third"]
可以保证找到用"third"
初始化的密钥。这种假设是错误的。单独但相同的字符串文字不能保证具有相同的地址。
解决方案:使用std::string
作为键,或者使用自定义的比较函数,根据字符串的内容对其进行比较。提示:使用std::strcmp
来实现函数。
p.S.您似乎没有operator[](...)
的任何过载,因此它不是">过载"。
我有什么不明白的地方吗?
是的,我认为您对代码及其意图感到困惑。严格来说,答案是你试图在一个只允许使用lvalues
的地方使用rvalue
,即在赋值的lhs上。为了解决这个直接的问题,你需要将你的运营商更改为:
char*& operator[](const char* key) { return data[key]; }
(即返回对包含在映射中的指针的引用)。这会编译,但我不认为这个结构会做你想做的事。例如,修改地图条目的内容字符串如下:
var["third"][0] = 'a';
如果您使用字符串文字来填充它,这将是未定义的行为,就像您在示例中所做的那样。
最好听从评论者的建议,改用std::strings
。
要使其编译,您必须将运算符[]签名更改为:
char*& operator[](const char* key) { return data[key]; }
但随后您将得到警告和可能的UB,因为字符串文字是常量数组,而您希望将其分配给非常量char*
。要使这些警告静音,您必须进行额外的更改,所有map::data["key"]
0到const char*
:
struct array{
std::map<const char*, const char*> data;
//constructor
array(const char* key, const char* value = ""){
data.insert(std::pair<const char*, const char*>(key, value));
}
//overloaded operator[] seems to be my problem
const char*& operator[](const char* key) { return data[key]; }
};
但也许这不是你想要的。
最好的解决方案是将std::map<const char*, char*>
转换为std::map<std::string, std::string>
- 将 char 指针传递给接受对 char 数组的引用的函数
- 枚举类的 C 样式强制转换到基础类型 char 的引用
- 成员引用基类型 'char' 不是 C++ 中的结构或联合
- 包括"lvtocon.h",未定义对'operator<<(std::ostream&, char const*)的引用
- 为什么要使用引用来获取 *char?当我们使用指针时,不使用引用不是更好吗?
- gtest - 未定义对"testing::InitGoogleTest(int*, char**)"的引用
- Qt5 对'QApplication::QApplication(int&, char**, int)'的未定义引用
- 悬空指向 int 和 char* 常量的指针/引用
- 来自类型为std::basic_string::const_iterator的非常量引用的无效初始化,并且<char>来自类型std::basic_string<char>::
- 类型为'std::string&的非常量引用的初始化无效,并且从类型为'std::basic_string<char>的右值
- 将 C++ 转换为 Python 通过引用返回无符号 char*
- 使用cout,如何将char转换为变量的地址/引用(?)
- 从运算符[]返回对映射的char*的引用
- Arduino:未定义的对"I2CRW::readByte(unsigned char, unsigned char)"的引用
- C# PInvoke - 返回 char* 和引用 char* 参数的函数
- 链接器错误(未定义的引用)与“静态 constexpr const char*”和完美转发
- 对'icu_56::UnicodeString::UnicodeString(signed char, unsigned short const*, int)' 的未定义引用
- 如何创建一个32位int和四个8位char类型的并集,每个类型都引用32位int的差分片
- __FILE__可以由C++中的const char*引用
- 从类型为"char*"的临时引用初始化类型为"char*&"的非常量引用