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

时间:2016-08-10 12:54:41

标签: c++ c++11

我有一个// C function void foo(char* buf); // C++ code std::string str("str"); foo(&str[0]); 类的对象需要传递给C函数,该函数通过遍历它并搜索空终止符号来操作std::string缓冲区。

所以,我有这样的事情:

&str[0]

假设我们使用C ++ 11,因此我们保证\0表示将具有连续存储的字符。

但我想知道是否有c_str指向以operator[]结尾的缓冲区?是的,有didFinishLaunchingWithOptions launchOptions:成员函数,但我在谈论var accessToken = "" if let key = NSUserDefaults.standardUserDefaults().objectForKey("accesstoken"){ accessToken = key as! String }

有人可以引用标准吗?

2 个答案:

答案 0 :(得分:7)

在实践中,是的。 std::string完全没有符合标准的实现,它们不会在缓冲区的末尾存储NUL字符。

所以如果你不想知道这个想法,你就完成了。

但是,如果你想知道该标准是否已被证实:

在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()更改,这是string通过const调用的状态可观察到的更改,我认为这是非法的。

绕过标准的另一种方法可能是,在您通过调用str[str.size()].data()或实际将.c_str()传递给{{}合法访问标准之前,不要初始化str.size() 1}}。由于除了标准中的那些元素之外没有定义的方法来访问该元素,因此您可以扩展并说NUL的延迟初始化是合法的。

我对此提出质疑,因为operator[]的定义意味着.data()的返回值是连续的,因此[]&[0]的地址相同,并且.data()保证指向NUL .data()+.size(),因此必须CharT,并且没有非(&[0])+.size()方法称为const的状态可能不会发生变化电话。

但是,如果编译器看起来并且看到你永远不会调用std::string.data(),那么如果可以证明你从不称呼它们,那么连续性的要求是否成立呢?

此时我会举起手来射击敌对的编译器。

这个标准非常被动地表达出来。因此,可能有一种方法可以使符合.c_str()的标准符合这些规则。并且由于保证越来越接近明确要求那里的NUL终结符,新的编译器出现的几率使用折磨的C ++读取来声称这符合标准是很低的。

答案 1 :(得分:5)

根据标准,是的。可以使用标准显示的string::datastring::c_str访问底层字符容器:

  

21.4.7.1 basic_string访问者[string.accessors]
  const charT* c_str() const noexcept;
  const charT* data() const noexcept;

     

1 返回:指针pp + i == &operator[](i)中每个i [0,size()]。{   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 返回: *(begin() + pos) if pos < size()否则,返回对值为charT的{​​{1}}类型的对象的引用,其中修改对象会导致未定义的行为。
  3 引发:没什么   4 复杂性:恒定时间。

因此charT()返回operator[size()],由于charT()std::stringstd::basic_string<char>charT()

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

请注意,修改true是UB。