为具有 C++ 字符串返回值的函数返回本地 C 字符串

Posted

技术标签:

【中文标题】为具有 C++ 字符串返回值的函数返回本地 C 字符串【英文标题】:Return a local C-string for function with C++ string return value 【发布时间】: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 字符串是在运行时创建的 【参考方案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 字符串,但仍然是一个字符串。 是的,很公平。不可否认的是,“字符串的副本”是被复制的,因为字符串的字节将被复制。

以上是关于为具有 C++ 字符串返回值的函数返回本地 C 字符串的主要内容,如果未能解决你的问题,请参考以下文章

C++程序中数组返回值的问题

C++函数的定义及使用

c++中为啥赋值运算符重载返回类型是引用

从函数 C++ 返回向量

c++如何用泛型控制返回值

Kotlin进阶系列-函数类型及函数字面值