【问题标题】:Return a local C-string for function with C++ string return value为具有 C++ 字符串返回值的函数返回本地 C 字符串
【发布时间】:2017-08-01 17:20:10
【问题描述】:

以下代码编译并运行,没有错误并具有预期的输出:

#include <string>
#include <iostream>
using namespace std;

string getString()
{
    char s[] = "Hello world!";
    return s;
}

int main()
{
    cout << getString() << endl;
}

我的问题是,这会一直有效吗?通常,如果您返回一个在本地声明的 C 字符串,您可能会遇到一些未定义的行为,但在这种情况下,这仍然是一个问题,因为它是通过字符串构造函数运行并(可能)复制到动态内存中的?

【问题讨论】:

  • std::string 添加到标准库的主要原因之一 - 它可以用作像 intdouble 这样的嵌入式类型,所以可以按值返回 std::string .
  • 你知道字符串litterals有静态存储持续时间:cpp-ref。因此,如果您的 c 字符串仅指向 const char* s="Hello World" 中的字符串文字,您可以安全地从函数中返回它,因为 s 是指向具有静态存储持续时间的对象的指针。这就是 std::except::what()type_info::name() 返回 c 字符串的原因
  • @Oliv 这是一个很好的事实,但这只是一个例子,在我的真实程序中,C 字符串是在运行时创建的

标签: c++ string


【解决方案1】:
 return s;

那一行相当于:

return std::string(s);

这将制作字符串的副本,所以没关系。

参考:http://en.cppreference.com/w/cpp/string/basic_string/basic_string(构造函数#5)

用 s 指向的以空字符结尾的字符串的副本初始化内容构造字符串。

编辑:更多细节。你提到

复制到动态内存中?

而答案可能是,也许,这并不重要。

std::string 提供的语义对此没有任何规范,它只是保证它可以被复制/移动并以一致的方式访问。如何实现这一点取决于库实现者。

事实上,std::string 的流行实现使用称为“Sma​​ll String O优化”的东西。特定长度以下的字符串存储在字符串对象本身中。

【讨论】:

  • 返回的临时 std::string 对象是从数组 s 构造(而不是复制!)。
  • 我想你是误解了,std::string 的构造函数复制了s 指向的字符串的内容。 s 仍然是一个字符串,一个 c 字符串,但仍然是一个字符串。
  • 是的,很公平。不可否认的是,“字符串的副本”是被复制的,因为字符串的字节将被复制。
猜你喜欢
  • 1970-01-01
  • 2012-09-16
  • 2013-10-30
  • 2021-12-27
  • 2014-11-06
  • 1970-01-01
相关资源
最近更新 更多