使用(char *)代替(const char *),获取std::string

3

std::string.c_str() 返回一个(const char*)值。我通过谷歌搜索发现可以进行以下操作:

std::string myString = "Hello World";
char *buf = &myString[0];

这怎么可能呢?&myString[0] 是一个 std::string 类型的对象,这怎么能行呢?
7个回答

9

&myString[0]std::string 类型的对象。

不是这样的。 myString[0] 是字符串的第一个字符的引用;&myString[0] 是该字符的指针。运算符优先级是这样的,它意味着 &(myString[0]) 而不是 (&mystring)[0]

请注意,以这种方式访问时,不能保证字符串将以零结尾;因此,如果您在期望零结尾字符串的 C 样式函数中使用它,则将依赖于未定义的行为。


1
在C++03中,“没有保证字符串将以零结尾”是正确的,但是C++11有这个保证。 - Tony Delroy
6
@TonyD: 不,C++11不保证存储在连续位置的字符后面会有一个零;只保证str[size]将给出对零值的引用,并且c_str()的结果将以null结尾。 - Mike Seymour
@MikeSeymour:我想知道为什么规范会把它搞得这么复杂。只是为了节省一个字节吗? - Nawaz
2
请参见21.4.7.1:const charT* c_str() const noexcept; const charT* data() const noexcept; 返回一个指针p,使得对于每个i在[0,size()]中,p + i == &operator。 因此,&p[i]引用以NUL结尾的字符串(正如c_str()所需)。 (您可能需要阅读https://dev59.com/_G025IYBdhLWcg3wUESP) - Tony Delroy
@TonyD:确实,c_str()需要返回指向连续终止数组的指针(正如我所说)。但是,对于小于size()的索引,operator[]仅需要提供对连续数组的引用;请参见21.4.5/2和21.4.1/5。一个适当的恶意实现可以保持未终止状态,直到有人调用c_str() - Mike Seymour
显示剩余2条评论

4

std::string::operator[](size_type pos)有const和非const两种重载形式,其中非const版本返回一个char&,因此您可以执行以下操作:

std::string s("Hello");
s[0] = 'Y';

请注意,由于s[0]返回的是char&,因此&s[0]是元素s[0]的地址。您可以将该地址分配给char*。如何使用此指针取决于您,请勿滥用。

3
这与运算符优先级有关。 [] 运算符的优先级高于取地址运算符 &,因此取地址运算符会作用于字符串 operator[] 函数返回的字符引用上。

+1 是指讨论优先级。这是从另一个角度看语法的方式。 - Nawaz

2
[] 操作符(std::string::char& operator[] (size_t pos))被重载,返回索引位置的字符的引用。获取该字符引用的地址是可以的。
因此,myString[0] 的返回类型不是 std::string,而是 char&
没有必要这样做。您可以直接进行操作 -
myString[0] = 'h';

2

std::string的方法c_str()operator[]是两种不同的方法,它们返回两种不同的类型。

方法c_str()确实返回一个const char*

const char* c_str() const;

然而,方法operator[]返回的是一个char的引用。当你取它的地址时,你得到的是一个char的地址。

       char& operator[] (size_t pos);
 const char& operator[] (size_t pos) const;

1
你错了。 &myString[0] 不是 std::string 类型,而是 char * 类型。 [] 运算符具有更高的优先级,并且 operator[] 返回对 char 的引用,其地址(& 运算符)是 char * 类型。

1

std::string类型有一个operator[],允许索引字符串中的每个字符。表达式myString[0]是对字符串第一个字符的(可修改)引用。如果您获取该引用的地址,则会得到指向数组中第一个字符的指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接