如何返回std :: string.c_str()

use*_*526 27 c++ string pointers return c++11

我有一个返回常量char指针的方法.它使用a std::string并最终返回其c_str()char指针.

const char * returnCharPtr()
{
    std::string someString;

    // some processing!.

    return someString.c_str();
}
Run Code Online (Sandbox Code Playgroud)

我从COVERITY工具得到一份报告,上面的说法不是很好.我已经google了,并且发现返回的char指针一旦someString遇到它的破坏就会失效.

鉴于此,如何解决这个问题?如何准确返回char指针?

返回std::string将解决此问题.但我想知道是否有其他方法可以做到这一点.

Lih*_*ihO 21

这段代码中发生的事情是:

const char * returnCharPtr()
{
    std::string someString("something");
    return someString.c_str();
}
Run Code Online (Sandbox Code Playgroud)
  1. std::string创建实例- 它是具有自动存储持续时间的对象
  2. 返回指向此字符串内部内存的指针
  3. 对象someString被破坏,其内部存储器被清除
  4. 此函数的调用者接收悬空指针(无效指针),这会产生未定义的行为

最佳解决方案:返回一个对象:

std::string returnString()
{
    std::string someString("something");
    return someString;
}
Run Code Online (Sandbox Code Playgroud)

  • 但为什么`const`?现在它无法移动. (3认同)

Mr.*_*C64 12

在C++中,最简单的方法就是返回std::string(由于像RVO和C++ 11移动语义这样的优化,这也很有效):

std::string returnSomeString()
{
    std::string someString;

    // some processing...

    return someString;
}
Run Code Online (Sandbox Code Playgroud)

如果你真的需要一个原始的C char*指针,你总是可以调用.c_str()返回的值,例如

// void SomeLegacyFunction(const char * psz)

// .c_str() called on the returned string, to get the 'const char*' 
SomeLegacyFunction( returnSomeString().c_str() );
Run Code Online (Sandbox Code Playgroud)

如果你真的想char*从函数返回一个指针,你可以在堆上动态分配字符串内存(例如使用new[]),并返回一个指针:

// NOTE: The caller owns the returned pointer, 
// and must free the string using delete[] !!!
const char* returnSomeString()
{
    std::string someString;

    // some processing...

    // Dynamically allocate memory for the returned string
    char* ptr = new char[someString.size() + 1]; // +1 for terminating NUL

    // Copy source string in dynamically allocated string buffer
    strcpy(ptr, someString.c_str());

    // Return the pointer to the dynamically allocated buffer
    return ptr;
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是提供目标缓冲区指针缓冲区大小(以避免缓冲区溢出!)作为函数参数:

void returnSomeString(char* destination, size_t destinationSize)
{
    std::string someString;

    // some processing...

    // Copy string to destination buffer.
    // Use some safe string copy function to avoid buffer overruns.
    strcpy_s(destination, destinationSize, someString.c_str());
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,第二个例子可能不是一个很好的主意。调用者不会期望他们必须删除该指针,并且很可能会导致内存泄漏。 (2认同)
  • @marsh呼叫者有责任检查他是否拥有返回的指针。 (2认同)

alk*_*alk 6

由于此问题标记为C,请执行以下操作:

#define _POSIX_C_SOURCE 200809L
#include <string.h>

const char * returnCharPtr()
{
  std::string someString;

  // some processing!.

  return strdup(someString.c_str()); /* Dynamically create a copy on the heap. */
}
Run Code Online (Sandbox Code Playgroud)

free()如果不再使用,请不要忘记函数返回的内容.


Art*_*amz 5

嗯,COVERITY 是正确的。您当前的方法失败的原因是std::string您在函数内创建的实例仅在该函数运行时才有效。一旦你的程序离开函数的作用域,std::string 的析构函数将被调用,这将是你的字符串的结尾。

但如果你想要的是 C 弦,怎么样......

const char * returnCharPtr()
{
    std::string someString;

    // some processing!.

    char * new_string = new char[someString.length() + 1];

    std::strcpy(new:string, someString.c_str());

    return new_string;
}
Run Code Online (Sandbox Code Playgroud)

但是等等...这几乎与返回 a 完全相同std::string,不是吗?

std::string returnCharPtr()
{
    std::string someString;

    // some processing!.

    return new_string;
}
Run Code Online (Sandbox Code Playgroud)

这会将您的字符串复制到函数范围之外的新字符串。它有效,但它确实创建了字符串的新副本。

感谢返回值优化,这不会创建副本(感谢所有更正!)。

因此,另一种选择是将参数作为参数传递,这样您就可以在函数中处理字符串,但不创建新的副本。:

void returnCharPtr(std::string & someString)
{
    // some processing!.
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要 C 字符串,则需要注意字符串的长度:

void returnCharPtr(char*& someString, int n) // a reference to pointer, params by ref
{
    // some processing!.
}
Run Code Online (Sandbox Code Playgroud)

  • 不要返回右值引用。它与左值引用有同样的问题。即使在 C++11 之前,(N)RVO 也会处理昂贵的返回复制,并且在 C++11 中,如果可以的话,对象将自动移出,而 (N)RVO 不起作用。 (4认同)

小智 3

最好的方法是返回一个std::string,它会为您进行自动内存管理。另一方面,如果您确实想返回 a const char*which 指向您从内部分配的某些内存returnCharPtr,那么它必须由其他人显式释放。

留下来std::string