我正在學習記憶化,并決定將這種技術應用于計算n-th Fibonacci數的遞回函式。我不確定我是否應該通過lvalue參考或rvalue參考來傳遞我的memo映射。
下面的兩個片段有什么不同嗎(關于性能和程式的一般表現)?哪一個是首選?另外,是否有辦法為第一個函式提供一個默認引數(map& memo = map{}不起作用,因為lvalue參考不會與rvalue系結...)?
版本#1
using map = std:: unordered_map<int, unsigned long long> 。
unsigned long long long fib(int n。map& memo){
if(memo.find(n) != memo.cend() ) return memo[n];
if(n <= 2) return 1;
memo[n] = fib(n - 1, memo) fib(n - 2, memo) 。
return memo[n]。
}
版本#2
using map=std:: unordered_map<int, unsigned long long> 。
unsigned long long long fib(int n。map& & memo = map{}){}
if(memo.find(n) != memo.cend() ) return memo[n];
if( n <= 2) return 1;
memo[n] = fib(n - 1, std::move(memo)) fib(n - 2, std::move(memo)) 。
return memo[n]。
uj5u.com熱心網友回復:
在C 中,移動一個物件對應于以下契約:
我不打算再使用這個物件。我將物件轉移到的人:你可以自由地使用這個物件的資源做任何你想做的事情。我保證在沒有給它分配一個新值的情況下不會再使用這個物件,所以我將永遠看不到你所做的任何事情的影響。所以,請你對我的物件做一些殘忍和不尋常的事情,如果這能讓你高興的話。現在,請考慮一下這行代碼:
memo[n] = fib(n - 1, std::move(memo))。 fib(n - 2, std::move(memo))。
在這里,你正在呼叫std::move(memo),這表明 "我保證不再使用memo"。然而,在同一行代碼中,你又在向memo[n]賦值,這意味著你確實打算以后使用memo。這就破壞了你與你std::move物件的人簽訂的契約。想象一下,這是你和 Fibonacci 的呼叫之間的對話:
- 你:嘿,Fibonacci 先生!我給你準備了一個備忘表。我給你準備了一個備忘表。它是百分之百屬于你的,而且我永遠不會再使用它。
- 斐波那契:好極了! 謝謝!
- 你。好吧,既然我剛剛給了你備忘表,我想把它涂成藍色,并在上面放上花。
- 斐波那契:等等,等一下!這已經不是你的桌子了。這不再是你的桌子了!
- 你。好吧,我還是要做。
- 菲波納奇:為什么,你這個小家伙!?(暴力隨之而來)
所以,是的。那是行不通的。
忽略任務。
忽略了對memo[n]的賦值,這里還有一個問題。你正試圖將同一個物件移動兩次給兩個不同的人。從你、第一個呼叫 Fibonacci 的人和第二個呼叫 Fibonacci 的人之間對話的角度來思考這意味著什么。
- 你:嘿,第一次呼叫斐波那契的先生!你是誰?這里有
memo。它是你的。你想用它做什么就做什么。沒有其他人會看到它。 - Mr. First Call to Fibonacci: Woohoo! 這真是太棒了!
- 你:嘿,第二位呼叫斐波那契的先生! 。這是
- Mr. Second Call to Fibonacci: Woohoo! 這真是太棒了!
- 第一任Fibonacci先生:等等,等一下!他們給了我
。他們把那個東西給了我! 他們不能把它給你!
- 第二位呼叫斐波納契的先生:你沒有聽嗎?他們剛剛把那個東西給了我!那是我的! 先生:你沒有聽嗎?它是我的!
- 第一個呼叫斐波納契的先生:為什麼,你這個小傢伙!?(暴力隨之而來)
memo。它是你的。你想用它做什么就做什么。沒有其他人會看到它。
所以是的,這不會有好結果。 :-)
從根本上說,只有當你或其他人打算再次使用該物件時,才能使用std::move。在記憶化的情況下,當一堆函式呼叫都需要協調在整個呼叫中共享同一個記憶化表時,這個要求并不成立,所以你不應該在這里使用rvalue語意。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/319319.html
標籤:
下一篇:將十進制數字轉換為二進制
