C++ 函数返回字符串

Posted

技术标签:

【中文标题】C++ 函数返回字符串【英文标题】:C++ function returning string 【发布时间】:2018-06-22 08:44:37 【问题描述】:
#include <iostream>

using namespace std;

string test(string s)

    string rv = "Hey Hello";
    if(s=="")
        return rv;
    else
        cout<<"Not returning"<<endl;



int main()

    string ss = test("test");
    cout<<ss<<endl;

上面的代码不应该返回任何值并且可能打印垃圾,但它返回“Hey Hello”即使在test函数的末尾没有return语句。 你能告诉我为什么它会这样吗?

【问题讨论】:

由于您的代码有Undefined Behaviour,任何事情都可能发生,包括似乎可以工作。作为一个疯狂的猜测,编译器可能会假设由于test 中的else 分支是非法的,所以if 条件必须始终为真,因此将函数优化为始终return rv; 因为UB.. "Hey Hello" 不是有效垃圾吗? ;-) 或者可能只是正确的状态巧合地留在了正确的寄存器中。您希望 rv 被清理和释放,但因为“Hey Hello”是一个 const char 序列,它可能会留在正确的位置。要理解这一点,最好的办法是查看它生成的程序集列表。 C and C++ functions without a return statement的可能重复 【参考方案1】:

在没有任何 return 语句的情况下返回非 void 的函数的末尾是 未定义的行为

如果它们处于活动状态,您应该对这类事情发出编译器警告

允许编译器假设未定义的行为是不可访问的,因此编译器可能已经删除了 if 语句并只保留了不会导致未定义行为的分支

【讨论】:

【参考方案2】:

真诚地,我很惊讶这段代码正在编译!您应该将警告视为错误。警告很重要。

我的猜测是编译器作者认为:

每当编码人员有一个没有返回语句的分支时,这可能意味着她知道无法访问该分支(例如,在调用函数之前检查参数的先决条件),因此可以删除该分支。

这可以解释为什么编译器会以这种方式运行。但是对您的问题的更正式的回答是:“这是未定义的行为,一切都可能发生”。

当尝试使用gcc 编译它时,输出取决于优化级别。

【讨论】:

【参考方案3】:

首先,您的 test 函数会导致未定义的行为,因为它不会返回,所以实际上任何事情都可能发生。

但是,如果我稍微推测一下,代码的行为可能是这样的,因为它意外地将曾经被 rv 局部变量占用的内存块解释为返回值。而那个对象恰好持有“Hello World”。因此,虽然函数没有正确返回,但堆栈和堆上的内存可以被解释为局部变量就是结果。

尽管如此,这只是一种猜测,根据 C++ 标准,这只是未定义的行为,这意味着您要么知道自己在做什么,并且永远不会让那个不返回的路径执行,要么代码就是错误的。

【讨论】:

【参考方案4】:

正如 Tyker 所说,这段代码会导致未定义的行为,这意味着一切都可能发生。

这很可能是由优化器引起的,它假设每个执行分支都返回一些值,并在此基础上优化最终代码。您应该尝试关闭优化,但请注意每个编译器都可以生成完全不同的结果。

看看这个函数的反汇编(clang 4.0,-O3)(我用char*代替std::string):

test: # @test
  mov eax, .L.str.1
  cmp rdi, rax
  je .LBB0_2 // <<-- IF .L.str.1 == "", goto .LBB0_2
  // CALL PRINTF
  push rax
  mov edi, .L.str.2
  xor eax, eax
  call printf
  add rsp, 8
  // END OF CALL PRINTF
  .LBB0_2:
  mov eax, .L.str // <<--- RETURN .L.str to the caller (optimization!)
  ret

.L.str:
  .asciz "Hey Hello"

.L.str.1:
  .zero 1

无论 if 语句结果如何,都会到达标签 .LBB0_2,因此在每种情况下都会返回它。

【讨论】:

“意味着一切都会发生” - 也许任何事情都可能发生 @codekaizer 好吧,一切都是任何事物的子集,所以如果有点不精确,这个陈述是正确的。

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

C++ 函数返回字符串

C++字符串函数返回语句

C++ 函数返回一个向量/字符串,但不是一个数组

C++:声明一个在头文件中返回字符串的函数?

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

字符串的简单使用,C++中函数返回字符串