微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

return 语句在这里的意义是什么?

如何解决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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?