【问题标题】:Are C++ strings mutable UNLIKE Java strings?C++ 字符串是否可变,与 Java 字符串不同?
【发布时间】:2022-06-28 13:54:33
【问题描述】:

以这种方式在 C++ 中操作字符串是否可以:

string s = "Sting";
s[2] = 'a';

它工作正常(并打印“Sting”),但这样做安全吗?

如果是,这是否意味着它们是可变的?

【问题讨论】:

  • 是的,std::strings 是可变的。然而,字符串文字不是。
  • 这很可能是 C++ 字符串。但是你应该澄清你的意思。
  • 注意:char* s = "content" 在 C++ 中已弃用,它应该是不可变的 const char* s = "content"。假设您示例中的字符串是 std::string,是的,std::string 和 chars 数组 s[] = "content"(不同于上面的 char*/const char*)是可变的。
  • @T.C:你所说的字符串文字是什么意思,伙计?我认为双引号中的任何内容都是字符串文字,并且如问题中的示例所示,它是可变的。
  • 不是。上面的例子在栈上创建了一个字符串对象,并初始化了内存。它拥有“Sting”。 C++ 一点也不像 Java。请找一本好的 C++ 书籍并阅读它。你会很高兴你做到了。

标签: c++ string


【解决方案1】:

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 是很常见的。如果是这种情况,更改字符串的任何元素都可能破坏正确的编码,例如,因为连续字节被其他内容替换。

所以,是的,字符串是可变的,但从语义的角度来看,分配给单个元素可能不安全。

【讨论】:

    【解决方案2】:

    字符串文字本身是不可变的,就像在 Java 中一样。

    字符串文字存储在内存的只读部分。

    例如,如果您执行以下操作,您将遇到段错误:

    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 字符串类的实例是不可变的。

    这是一个显示字符串具有副本这一事实的示例:

    #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;
    }
    

    【讨论】:

    • 请解释字符串文字不是不可变的意思。我的意思是,字符串文字中双引号中的任何内容,对吗?在我提供的例子中,我们确实改变了它。请大哥解释一下。
    • 是的,双引号中的任何内容都是字符串文字。该字符串存储在内存的只读部分。因此它是不可变的,因为你不能写入这个内存。在您提供的示例中,您没有改变字符串文字。您改变了存储在 String 对象中的它的副本。我会打一个例子,使这个概念非常清楚。
    • @AnonymousAndy - 示例中的第一行采用字符串文字,并根据文字创建一个 std::string object。它在概念上与您所做的 int a = 1; 没有什么不同。您可以更改 a 的值,对吗?但是你不能改变1
    【解决方案3】:

    是的,是的。

    这就像在位置 2 处修改数组。

    【讨论】:

      【解决方案4】:

      是的,它是绝对安全的,是的,字符串是可变的,这意味着您可以更改它们,向它们添加新内容,也可以从中删除部分内容。

      【讨论】:

        【解决方案5】:

        C++ std::string 是可变的,赋值(通常)复制字符串数据。 Java String 是不可变的,赋值复制对字符串的引用。

        std::shared_ptr&lt; const std::string &gt; 类型在某种程度上类似于 Java 字符串。然而,这是一个穷人的替代品。在 C++03 中,它与优化相关,例如字符串集合的排序,但对于 C++11 移动语义,它不再与任何事物相关——学术 POV 除外。

        【讨论】:

          【解决方案6】:

          C++ 中的字符串是可变的,但能力越大,责任越大:如果您读取或存储到越界的字符串内存,您将得到未定义的行为。例如,在您的示例中,如果您引用 s[12],您将得到未定义的行为。

          【讨论】:

            【解决方案7】:

            细绳 C++ 可变。 (复制的字符串数据) Python 不可变(复制的字符串引用) Java 不可变(复制的字符串引用)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-09-24
              • 2011-10-07
              • 2013-09-16
              • 2015-04-15
              • 1970-01-01
              • 1970-01-01
              • 2016-08-10
              • 2013-05-08
              相关资源
              最近更新 更多