我经常使用std :: string作为通用二进制缓冲区。这会导致获取可变数据指针的问题,因为当字符串&s.front()
为空时,您无法使用s
。
这就是为什么我有这个辅助函数(它首先执行string :: data应该做什么):
char* data(string& s)
{
if (!s.empty())
return &s.front();
else
return const_cast<char*>(s.data());
}
这与标准一致,因为字符串是连续存储的,并且不允许覆盖终止0字符。
我喜欢它,因为似乎尺寸检查得到了优化。
但我更希望这个功能:
char* data(string& s)
{
return const_cast<char*>(s.data());
}
我只是不确定这样做是否合法。
毫无疑问它会起作用,如果尺寸检查没有得到优化,我会使用这个版本。
答案 0 :(得分:0)
我认为没有注意到的一个怪癖。这似乎是一个极端的边缘情况,我只是通过仔细阅读来解决。 string::data
保证它返回的缓冲区包含字符串和空终止符。 std::string
但是不保证其缓冲区的空终止符。
因此,我认为技术上符合要求的实现在创建字符串或调用string::front
时无法添加空终止符,并且仅在调用string::data
或string::c_str
时添加它
因此,即使你得到的指针是相同的,我也不确定副作用是否保证相同,这些不一定相同。 (在有人询问这对const
字符串有什么用处之前,我不明白为什么确认实现无法声明内部缓冲区mutable
并修改null,即使对于const
函数也是如此执行适当的锁定以使同时访问安全。)
然而,实际上这样做的实施似乎是高度恶劣设计或积极残忍。
答案 1 :(得分:-1)
标准说data() == &operator[](0)
,它是对第一个字符的引用的地址。 &front()
也相当于&operator[](0)
。 operator[](0)
返回对第一个字符的引用,因此无论它是否为常数都无关紧要,它们的地址必须相等。
但是现在我不能完全确定你是否真的被允许通过返回的指针修改字符串(即使现在我知道它指向可修改的数据)。我几乎可以肯定你可以,因为该函数采用了一个非对象引用,但如果我无法弄明白,那就是另一个问题。
令人难以置信的是,在这样一个简单的单行函数中涉及到多少微妙之处。