C++11 data()是否保证等于&;非空字符串的front()?

C++11 data()是否保证等于&;非空字符串的front()?,c++11,C++11,我经常使用std::string作为通用二进制缓冲区。这会导致获取可变数据指针时出现问题,因为当字符串s为空时,无法使用&s.front() 这就是为什么我有这个helper函数(它做string::data首先应该做的事情): char*数据(字符串&s) { 如果(!s.empty()) 返回&s.前(); 其他的 返回常量转换(s.data()); } 这与标准一致,因为字符串是连续存储的,不允许覆盖终止的0字符 我喜欢它,因为它看起来尺寸检查得到优化了 但我更希望这个函数: char*

我经常使用std::string作为通用二进制缓冲区。这会导致获取可变数据指针时出现问题,因为当字符串
s
为空时,无法使用
&s.front()

这就是为什么我有这个helper函数(它做string::data首先应该做的事情):

char*数据(字符串&s)
{
如果(!s.empty())
返回&s.前();
其他的
返回常量转换(s.data());
}
这与标准一致,因为字符串是连续存储的,不允许覆盖终止的0字符

我喜欢它,因为它看起来尺寸检查得到优化了

但我更希望这个函数:

char* data(string& s)
{
    return const_cast<char*>(s.data());
}
char*数据(字符串&s)
{
返回常量转换(s.data());
}
我只是不确定这样做是否合法


毫无疑问,它会起作用,如果没有优化尺寸检查,我会使用这个版本。

标准上说
data()==&operator[](0)
,这是第一个字符的引用地址
&front()
也相当于
运算符[](0)
运算符[](0)
返回对第一个字符的引用,因此不管它是否为常量,它们的地址必须相等

但是现在我不能完全确定是否允许您通过返回的指针修改字符串(尽管现在我知道它指向可修改的数据)。我几乎可以肯定你可以,因为这个函数使用了一个非标准引用,但如果我不能理解它,那是另一个问题


令人难以置信的是,这么简单的一行函数包含了如此多的微妙之处。

一个我认为尚未注意到的怪癖。这似乎是一个极端的边缘案例,我只是通过仔细阅读才得出结论<代码>字符串::数据保证它返回的缓冲区包含字符串和空终止符<但是,代码>标准::字符串并不保证其缓冲区中有空终止符

因此,我认为技术上一致的实现不能在创建字符串或调用
string::front
时添加空终止符,只能在调用
string::data
string::c_str
时添加空终止符

因此,即使你得到的指针是相同的,我也不确定副作用是否保证是相同的,这使得它们不一定相等。(在有人问这将如何处理
const
字符串之前,我不明白为什么确认实现不能声明内部缓冲区
mutable
并修改空值,即使是
const
函数,假设它执行了适当的锁定以确保同时访问的安全。)


然而,实际执行此操作的实现看起来要么设计非常糟糕,要么非常残酷。

使用
std::vector
作为缓冲区,
std::string
不应用于此目的。@Xeo我发现字符串更方便。它提供基本相同的功能,但使字符串自动缓冲,而无需复制它们。谷歌的协议缓冲区也在使用它们,这让我陷入其中。这是到处都在尖叫的未定义行为。不要这样做。不要宣传这个。不要在我的团队里工作。您将无法生存第1天。标准($21.4.7.1)禁止修改此数据:
const charT*data()const noexcept。。。要求:程序不得更改字符数组中存储的任何值。
@mockinterface我认为这与此无关,因为您将非ST字符串作为参数,data()返回一个指针,对于非空字符串,该指针必须指向front(),因此可以修改它,因为您可以访问front()的非ST版本。如何获取指针有什么关系?通过非标准引用传递实例不允许执行标准禁止的操作。举例来说,如果我在度假时把一只猫放在一个猫咪度假胜地,我希望他们给它喂食和洗澡,但不给它剃毛。撇开猫不谈,我不熟悉一个不允许你改变字符串缓冲区的库——很多人都从事这种实践,但标准的语言是明确的。@mockinterface标准明确允许你修改指向非ST数据成员的指针,即使是通过常量指针(这就是常量cast的用途)。因此,我的理解是,您的引用仅适用于常量字符串(是的,它是多余的),否则将与标准相矛盾。但是如果能有其他的意见,那就太好了,因为我们可能不会在这里解决它。
front()
返回对第一个字符的非常量引用。你可以随意改变第一个角色,直到你觉得无聊为止。通过获取地址检索的指针不得更改。对指针执行任何类型的算术都是未定义的行为,即使您从未取消引用它。取消引用此修改的指针同样是未定义的行为。将空终止符添加为
c_str()
的“
mutable
”副作用将违反有关数据竞争的标准库规则。但是它符合C++03的要求。@Potatoswatter即使库采取了适当的预防措施来同步更改,这种情况会发生吗?也许有一个内部互斥?(我确实意识到这有点荒谬,但我很想知道这是否是一种实际的、可能证实的行为)[res.on.data.races]/3:“C++标准库函数不应修改除了当前线程之外的线程可访问的对象,除非对象直接或间接地通过函数的非<代码> const 参数访问,包括<代码> < <代码>”和/ 5:C++标准库函数不应访问容器参数的元素,除非调用其规范所要求的函数。
char* data(string& s)
{
    return const_cast<char*>(s.data());
}