在C++中这样操作字符串可以吗:
string s = "Sting";
s[2] = 'a';
它运行得很好(并打印出 'String'),但这样做是否安全?
如果是,这是否意味着它们是可变的?
C++字符串字面值,例如"literal"
,是不可变的,尽管C++03允许将指针分配给这样的字面值char*
(这个特权在C++11中被弃用和删除)。试图更改字符串字面值的字符是未定义的行为:
char* s = "literal"; // OK with C++03; illegal with C++11 and later
s[0] = 'x'; // undefined behavior
C++中的std::string
对象如果没有声明为std::string const
,则可以被修改。如果您认为char
对象序列相互独立,则可以将值分配给单个对象。然而,通常字符串实际上包含以UTF-8字节编码的Unicode。如果是这种情况,更改字符串中任何元素可能会破坏正确的编码,例如因为连续字节被替换为其他内容。
因此,是的,这些字符串是可变的,但从语义角度考虑,逐个分配值可能不安全。
字符串字面量本身与 Java 中一样是不可变的。
字符串字面量存储在只读内存部分中。
例如,如果您执行以下操作,将会得到一个 segfault(段错误):
char *ptr = (char *) "hello";
ptr[0] = 'a'; //segfault! you can't change something that's immutable
然而!你可以使用s[2] = 'a'
来修改字符串,除非该字符串用const关键字声明。
原因是字符串的=
运算符是重载的,它以字符串字面量为参数,然后循环遍历字符串字面量并将每个字符复制到可变的char数组中。
因此,如果你在Java和C/C++中比较字符串字面量,它们在不可变性方面具有相同的行为。C++字符串类的实例是可变的,但Java String类的实例是不可变的。
以下是一个示例,显示该字符串具有副本:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char *ptr = "hello";
string s = ptr;
s[0] = 'b';
cout << s << endl; //prints bello
cout << ptr << endl; //prints hello
return 0;
}
对象
。这在概念上与你做int a = 1;
没有任何区别。你可以改变a
的值,对吧?但你不能改变1
。 - PaulMcKenziestd::string
是可变的,而赋值(通常)会复制字符串数据。Java中的String
是不可变的,赋值会复制对字符串的引用。std::shared_ptr< const std::string >
在某种程度上类似于Java字符串。然而,它只是C++中的一个贫民版替代品。在C++03中,它对优化例如排序字符串集合等方面有一定意义,但随着C++11移动语义的出现,它已经不再对任何事情产生影响了——除了学术观点外。是的,没错。
这就像在位置2修改一个数组。
没错,它是完全安全的,是可变字符串,这意味着您可以更改它们,附加新内容并从中删除部分。
字符串 C++ 可变的。(字符串数据被复制) Python 不可变的。(字符串引用被复制) Java 不可变的。(字符串引用被复制)
std::string
是可变的。然而,字符串字面值是不可变的。 - T.C.char* s = "content"
已经被弃用,应该使用不可变的const char* s = "content"
。假设你的示例字符串是一个std::string,那么std::string和字符数组s[] = "content"(与上面的char*/const char*不同)是可变的。 - user2249683"String"
是一个字符串字面值。它的值用来初始化s
,它是类型为std::string
的一个对象,而不是一个字符串字面值。字符串字面量是不可变的;s
则不是。 - Keith Thompson