繁体   English   中英

将C ++ 11 std :: string :: operator []返回以null结尾的缓冲区

[英]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::datastring::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::stringstd::basic_string<char>charT()'\\0'

这意味着,在您的情况下, *(&str[0] + str.size()) == '\\0'应根据标准始终为true


请注意,修改operator[size()]是UB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM