【问题标题】:What is the lifetime of the result of std::string::c_str()?std::string::c_str() 结果的生命周期是多少?
【发布时间】:2011-09-21 07:57:19
【问题描述】:

在我的一个程序中,我必须与一些适用于const char* 的遗留代码进行交互。

假设我有一个看起来像这样的结构:

struct Foo
{
  const char* server;
  const char* name;
};

我的高级应用程序只处理std::string,所以我想到了使用std::string::c_str() 来取回const char* 指针。

但是c_str() 的生命周期是多少?

我可以做这样的事情而不会遇到未定义的行为吗?

{
  std::string server = "my_server";
  std::string name = "my_name";

  Foo foo;
  foo.server = server.c_str();
  foo.name = name.c_str();

  // We use foo
  use_foo(foo);

  // Foo is about to be destroyed, before name and server
}

或者我应该立即将c_str() 的结果复制到另一个地方?

谢谢。

【问题讨论】:

  • 当我在函数中定义一个本地字符串并返回 .c_str() 时发生在我身上。我不明白为什么有时我只得到字符串的一部分,直到我明白const char* 不会永远存在,但直到字符串被销毁

标签: c++ string c-strings lifetime c-str


【解决方案1】:

只要字符串没有被破坏或修改,使用 c_str() 就可以了。如果使用先前返回的 c_str() 修改了字符串,则实现定义。

【讨论】:

    【解决方案2】:

    c_str() 的返回值仅在下一次调用同一字符串的非常量成员函数之前有效

    【讨论】:

      【解决方案3】:

      在对应的string对象发生以下一种情况之前有效:

      • 对象被销毁
      • 对象被修改

      除非您在将c_str()s 复制到foo 之后但在调用use_foo() 之前修改那些string 对象,否则您的代码没有问题。

      【讨论】:

        【解决方案4】:

        如果std::string 被销毁或调用字符串的非常量成员函数,则c_str() 结果无效。所以,如果你需要保留它,通常你会想要复制它。

        在您的示例中,c_str() 的结果似乎可以安全使用,因为在该范围内字符串不会被修改。 (但是,我们不知道 use_foo()~Foo() 可能会对这些值做什么;如果他们将字符串复制到其他地方,那么他们应该执行真正的复制,而不仅仅是复制char 指针。)

        【讨论】:

        • c_str() 如果 std::string 对象是超出范围或调用线程创建函数的自动对象,则指针可能无效。
        • 你能解释一下non-const member function of the string is called.吗?
        • “非 const 成员函数”是任何未用 const 关键字标记的成员函数。这样的函数可能会改变字符串的内容,在这种情况下,字符串可能需要为c_str() 返回的字符串的空终止版本重新分配内存。例如size()length()const,所以你可以调用它们而不用担心字符串改变,但clear()不是const
        【解决方案5】:

        c_str() 返回的const char* 仅在下一次对std::string 对象的非常量调用之前有效。在这种情况下,您很好,因为您的 std::string 仍在 Foo 的生命周期内,并且您没有执行任何其他会在使用 foo 时更改字符串的操作。

        【讨论】:

          【解决方案6】:

          从技术上讲,您的代码没问题。

          但是你写的方式很容易让不知道代码的人破解。对于 c_str() ,唯一安全的用法是将其作为参数传递给函数。否则,您将面临维护问题。

          示例 1:

          {
            std::string server = "my_server";
            std::string name   = "my_name";
          
            Foo foo;
            foo.server = server.c_str();
            foo.name = name.c_str();
          
            //
            // Imagine this is a long function
            // Now a maintainer can easily come along and see name and server
            // and would never expect that these values need to be maintained as
            // const values so why not re-use them
          
            name += "Martin";
            // Oops now its broken.
          
            // We use foo
            use_foo(foo);
          
            // Foo is about to be destroyed, before name and server
          }
          

          所以为了维护让它显而易见:

          更好的解决方案:

          {
            // Now they can't be changed.
            std::string const server = "my_server";
            std::string const name   = "my_name";
          
            Foo foo;
            foo.server = server.c_str();
            foo.name = name.c_str();
          
            use_foo(foo);    
          }
          

          但如果你有 const 字符串,你实际上并不需要它们:

          {
            char const* server = "my_server";
            char const* name   = "my_name";
          
            Foo foo;
            foo.server = server;
            foo.name   = name;
          
            use_foo(foo);
          }
          

          好的。出于某种原因,您希望它们作为字符串:
          为什么不只在通话中使用它们:

          {
            std::string server = "my_server";
            std::string name = "my_name";
          
            // guaranteed not to be modified now!!!     
            use_foo(Foo(server.c_str(), name.c_str());
          }
          

          【讨论】:

            【解决方案7】:

            为了完整起见,这里是reference and quotation from cppreference.com

            c_str()获得的指针可能会被以下行为无效:

            • 将对字符串的非常量引用传递给任何标准库函数,或者
            • string上调用非常量成员函数,不包括operator[]at()front()back()begin()rbegin()end()rend()。李>

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-16
              • 2021-09-25
              • 2022-10-27
              • 1970-01-01
              • 1970-01-01
              • 2016-05-16
              相关资源
              最近更新 更多