如何解决return 语句在这里的意义是什么?
这里的return语句有什么意义? [问题:N_queen 问题] 当我不使用 return 调用时,该函数可以工作。但是当我在递归调用中使用 return 语句时它不起作用[我在代码中提到过]。请解释一下,如果可能,您能否通过跟踪调用(即控件如何移动)来解释?
#include <iostream>
#include <bitset>
using namespace std;
bitset<30> cols,diag1,diag2; //all zeros
void Nqueen(int n,int row,int& ans){
if(row==n){
ans++;
return;
}
//moving across each column
//k is iterator for columns
for(int k=0;k<n;k++){
if(!cols[k] && !diag1[row+k] && !diag2[row-k+n-1]){
cols[k]=diag1[row+k]=diag2[row-k+n-1]=1;
Nqueen(n,row+1,ans); //this recursion call I am talking about.
// if I comment out the above recursion call and instead write
// return (Nqueen(n,rows+1,ans));
// It outputs 0 for any input n
cols[k]=diag1[row+k]=diag2[row-k+n-1]=0; //backtracking
}
}
}
int main(){
int n; cin>>n; //size of board(square matrix)
int ans=0;
Nqueen(n,ans);//0 is for 1st row
cout<<ans<<endl;
}
解决方法
不同之处在于编译器将在知道函数为 void
的情况下执行优化,这意味着不需要返回任何值。
当您使用 return (Nqueen(n,row+1,ans));
时,您是在指示编译器生成一个代码,该代码将计算 Nqueen
的值,然后将其返回给函数的调用者。然而,由于函数是 void
,编译器会理解不需要执行计算,因为它不会被返回,所以他只会生成一个返回。
如果你想看看编译器做了什么,你可以在汇编程序中翻译这两个版本,将 -S
标志传递给编译器并比较差异。以下是 aarch64 (arm64) 汇编器中两个版本的区别:
diff test-normal.s test-return.s
2c2
< .file "test-normal.cpp"
---
> .file "test-return.cpp"
265,309c265
< ldrsw x0,[sp,68]
< add x1,sp,72
< mov x8,x1
< mov x1,x0
< adrp x0,cols
< add x0,x0,:lo12:cols
< bl _ZNSt6bitsetILm30EEixEm
< ldr w1,56]
< ldr w0,68]
< add w0,w1,w0
< sxtw x0,w0
< add x1,88
< mov x8,diag1
< add x0,:lo12:diag1
< bl _ZNSt6bitsetILm30EEixEm
< ldr w1,68]
< sub w1,w0
< ldr w0,60]
< add w0,w0
< sub w0,w0,#1
< sxtw x0,104
< mov x8,diag2
< add x0,:lo12:diag2
< bl _ZNSt6bitsetILm30EEixEm
< add x0,104
< mov w1,0
< bl _ZNSt6bitsetILm30EE9referenceaSEb
< mov x1,x0
< add x0,88
< bl _ZNSt6bitsetILm30EE9referenceaSERKS1_
< mov x1,72
< bl _ZNSt6bitsetILm30EE9referenceaSERKS1_
< add x0,104
< bl _ZNSt6bitsetILm30EE9referenceD1Ev
< add x0,88
< bl _ZNSt6bitsetILm30EE9referenceD1Ev
< add x0,72
< bl _ZNSt6bitsetILm30EE9referenceD1Ev
---
> b .L7
如您所见,不同之处在于,在正常情况下,编译器生成递归代码,而在带有 return 语句的情况下,生成单个 b
(分支)指令以返回 whiteout计算。因此,编译器优化了生成的代码,因为它知道计算出的值永远不会返回。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。