[英]Will C++11 std::string::operator[] return null-terminated buffer
我有一个std::string
类的对象,我需要传递给C函数,通过迭代它并搜索空终止符号来操作char*
缓冲区。
所以,我有这样的事情:
// C function
void foo(char* buf);
// C++ code
std::string str("str");
foo(&str[0]);
假设我们使用C ++ 11,因此我们保证std::string
表示将具有连续存储的字符。
但我想知道是否有任何保证&str[0]
将指向以\\0
结尾的缓冲区? 是的,有c_str
成员函数,但我在谈论operator[]
。
有人可以引用标准吗?
在实践中,是的。 std::string
实现正好是符合标准的,不会在缓冲区的末尾存储NUL字符。
所以,如果你不想知道这个想法,你就完成了。
但是,如果您想知道该标准是否为abtruse:
在C ++ 14中,是的。 明确要求[]
返回一组连续的元素, [size()]
必须返回一个NUL字符,而const方法可能不会修改状态。 因此*((&str[0])+size())
必须与str[size()]
,并且str[size()]
必须是NUL,因此游戏结束。
在C ++ 11中,几乎可以肯定。 有一些规则, const
方法可能无法修改状态。 可以保证data()
和c_str()
返回一个以空值终止的缓冲区,该缓冲区在每个点都与[]
一致。
对C ++ 11标准进行复杂的阅读会说明在调用data()
或c_str()
, [size()]
不会在缓冲区的末尾返回NUL终止符,而是返回static const CharT
单独存储,缓冲区具有NUL应该是的单位化(甚至是陷阱值)。 由于要求const
方法不能修改状态,我认为这种读数是不正确的。
这要求&str[str.size()]
在.data()
调用之间发生变化,这是一个const
调用中string
状态的可观察变化,我认为这是非法的。
绕过标准的另一种方法可能是不初始化str[str.size()]
直到您通过调用.data()
.c_str()
或实际将str.size()
传递给operator[]
来合法访问它。 由于除了标准中的那些元素之外没有定义的方法来访问该元素,因此您可以扩展并说NUL的延迟初始化是合法的。
我对此提出质疑,因为.data()
的定义暗示[]
的返回值是连续的,因此&[0]
与.data()
和.data()+.size()
地址相同保证指向NUL CharT
所以必须(&[0])+.size()
,并且没有非const
方法调用std::string
的状态可能不会在调用之间改变。
但是,如果编译器可以看到并且看到你永远不会调用.data()
或.c_str()
,那么如果可以证明你从未调用它们,那么连续性的要求是否成立呢?
在这一点上,我举起手来射击敌对的编译器。
这个标准非常被动地表达出来。 因此,可能有一种方法可以使符合std::string
符合这些规则。 并且由于保证越来越接近明确要求那里的NUL终结符,因此新编译器出现的使用C ++的折磨读取声称符合标准的可能性很低。
根据标准,是的。 可以使用string::data
或string::c_str
访问底层char容器,标准上说:
21.4.7.1
basic_string
访问器[string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;
1 返回:指针
p
,使得p + i == &operator[](i)
为[0,size()]
每个i
。
2 复杂性:恒定时间。
3 要求:程序不得更改存储在字符数组中的任何值。
并且为了证明它是空终止的,看一下operator[]
定义(强调我的):
21.4.5
basic_string
元素访问[string.access]
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
1 要求:
pos <= size().
2如果pos < size()
则返回:*(begin() + pos)
pos < size()
。 否则,返回对charT
类型的对象的引用,其值为charT()
,其中修改对象会导致未定义的行为。
3 投掷 :没什么。
4 复杂性 :恒定时间。
因此operator[size()]
返回charT()
,因为std::string
是std::basic_string<char>
, charT()
是'\\0'
。
这意味着,在您的情况下, *(&str[0] + str.size()) == '\\0'
应根据标准始终为true
。
请注意,修改operator[size()]
是UB。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.