C ++函数返回字符串

时间:2018-06-22 08:44:37

标签: c++ string c++11

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Filtered Rows" = Table.SelectRows(Source, each Text.StartsWith([firstname], "Ab")),
    TopHalfRows = Number.RoundUp(Table.RowCount(#"Filtered Rows") / 2),
    KeepTopHalf = Table.FirstN(#"Filtered Rows", TopHalfRows)
in
    KeepTopHalf

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

4 个答案:

答案 0 :(得分:5)

到达没有任何return语句的非空返回函数的末尾是 不确定的行为

如果此类活动处于活动状态,则应该向编译器发出警告

允许编译器假定未定义的行为是无法实现的,因此编译器可能已删除了if语句,并仅保留了不会导致未定义行为的分支

答案 1 :(得分:1)

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

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

只要编码器的分支没有返回语句,就可能意味着她知道无法访问该分支(例如,在调用函数之前检查了参数的前提条件),因此可以删除该分支。

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

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

答案 2 :(得分:0)

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

但是,如果我稍作推测,该代码的行为可能是这样的,因为它意外地将曾经由rv局部变量占用的内存块解释为返回值。而那个物体恰好持有“ Hello World”。因此,尽管该函数未正确返回,但是可以将堆栈和堆上的内存解释为本地变量是结果。

不过,这只是一个猜测,按照C ++标准,这只是未定义的行为,这意味着您知道自己在做什么,并且永远不要执行该返回路径或代码是错误的。

答案 3 :(得分:0)

正如泰克所说,此代码会导致不确定的行为,这意味着一切都会发生。

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

看看这个函数的反汇编(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

达到.LBB0_2标签,无论是否生成语句,因此在每种情况下都将返回它。