这个简单的C++函数有什么问题?

use*_*602 4 c++ function

这是一个来自interiew的问题,以及下面的代码.这个功能有什么问题?

string f() {
    return "hello world";
}
Run Code Online (Sandbox Code Playgroud)

对我来说,没有任何错误,我甚至可以使用此功能运行程序:

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

string f() {
    return "hello world";
}

int main() {
    string s2=f();
    cout<<s2<<endl;
}
Run Code Online (Sandbox Code Playgroud)

什么错这个功能呢?

use*_*956 6

嗯......有一些安慰,在这类问题中,往往没有正确的答案.你可能希望最好的方法是通过展示你的专业知识来详细说明利弊(也就是代码手淫)来让面试官惊叹不已.

从样式的角度来看,使用按值返回返回对象往往很糟糕.考虑:

X f();

X x;
x = f();
Run Code Online (Sandbox Code Playgroud)

f分配一个X.需要返回一个X,因此在堆栈上放置一个额外的副本作为返回值.最后,堆栈上的x通过赋值运算符复制到x中.总共有3个X出现在内存中.有人可能会说这是低效的,因此当值是对象时,您应该尝试不按值返回.

然而,一位更精明的受访者可能会指出:

  • 一些编译器优化了临时副本.对于这种优化,我认为在这里是否通过复制构造函数或相等运算符进行X的赋值会产生影响.说"复制elison",看看面试官是否抬起眉毛:什么是复制省略以及如何优化复制和交换习语?.我猜复制省略可能在这里工作,因为该功能在同一个翻译单元中,因此很容易内联.
  • 几乎所有字符串类的实现都会在写入时实现copy,其中在这种情况下将保留字符串的文本数据的单个副本,其余数据保存在堆栈上,并且当字符串为时基本上不会产生任何开销复制.
  • 如果你正在使用早期版本的visual studio,内存泄漏就会随之而来

那么,还有什么选择?

X const& f();
Run Code Online (Sandbox Code Playgroud)

可以考虑作为替代方案.但是,这有其自己的样式问题,因为调用者不清楚结果的生命周期.也许下次调用会使之前的参考结果无效?谁知道?

void f_get( X& result );
Run Code Online (Sandbox Code Playgroud)

可能是首选(由一些采访者).这有以下好处:

  • 没有局部变量的副本
  • 没有不确定的生命周期的引用/指针
  • 在X是字符串的情况下,只保留一个文本数据的副本(尽管所有情况都是如此)

在这两者中,牺牲了可读性 - 在一般情况下,调用者现在必须更加注意哪些参数是功能参数,哪些是用于保存结果.

在OP中,堆栈中字符串文字的生命周期也不是很明显.当函数返回时是否从堆栈中取消分配?可能不是 - 它可能保存在静态内存区域(最好检查规格是否确定).但如果没有,那么结果是什么 - 可能没有,因为字符串可能会在堆上创建char const*的副本,除非你有一些奇怪的字符串实现,他们的构造函数可以通过一些聪明的模板类型告诉区分文字和非文字参数 - 魔法.

在任何情况下,像这样喷射一些BS肯定会得分,如果没有标记.

你的控制台输出ascii,UTF-8还是unicode?这个程序可能对其中一个人来说是错误的,而且在没有说英语的地方也是错误的.

您是否检查过stdout是否具有有效值,或者您是否在Windows中没有-D_CONSOLE进行编译,或者某些嵌入式设备或游戏控制台中没有stdout,您必须重定向到日志库(或崩溃)?

嗯......接受你的选择.

临时副本可能是他们正在寻找的机器人.因为在一个字符串的情况下暂时没有任何后果(也可能是复制省略),面试官闻到了接骨木果子,而他的母亲是一只山羊