這部分可重點參考《c++ primer 》第5版 p608-p614,寫的很透徹。forward的使用
#include
#include
#include
using
namespace std;
template
<
typename t>
void
print
(t& t)
template
<
typename t>
void
print
(t&& t)
template
<
typename t>
void
testforward
(t && v)
intmain()
forward的原始碼// function template forward
template
<
class
_ty>
_nodiscard constexpr _ty&&
forward
(remove_reference_t<_ty>
& _arg)
noexcept
template
<
class
_ty>
_nodiscard constexpr _ty&&
forward
(remove_reference_t<_ty>
&& _arg)
noexcept
可以看到大致意思是分別對左值引用和右值引用分別使用不同的模板函式,都返回了static_cast<_ty&&>(_arg)
,看不出什麼思路,先看看remove_reference_t<_ty>
// struct template remove_reference
template
<
class
_ty>
struct remove_reference ;
template
<
class
_ty>
struct remove_reference<_ty&
>
;template
<
class
_ty>
struct remove_reference<_ty&&
>
;template
<
class
_ty>
using remove_reference_t =
typename remove_reference<_ty>
::type;
很顯然就是針對不同型別,t,t &,t &&,分別過載,定義出只返回不帶引用符號的t。知道了這個,還是無濟於事。那先看看move原始碼,說不定有思路。
// function template move
template
<
class
_ty>
_nodiscard constexpr remove_reference_t<_ty>
&&move
(_ty&& _arg)
noexcept
可以看到傳入的是右值引用,返回的也是static_cast
後的右值引用。很簡潔了,但卻看不出所以,所以必然是語言特性了,也就是引用摺疊。
引用摺疊
一般情況下,不允許將右值引用繫結到左值上。但是有兩個例外:
template
<
typename t>
void
f(t&&
);
當將乙個左值傳遞給函式的右值引用引數,並且此右值引用引數指向模板型別引數(t&&) ,編譯器推斷模板引數為實參的左值引用型別。即為:對於左值int i;,f(i)推斷出t的型別為 **int&**而非int,這樣看起來就像是int& &&。
引用摺疊規則。t& &、t& &&、t&& &
都摺疊為t&
,t&& &&摺疊為
t&&`.
再看move
// function template move
template
<
class
_ty>
_nodiscard constexpr remove_reference_t<_ty>
&&move
(_ty&& _arg)
noexcept
這時候就發現其實他也沒幹什麼大事,引數是右值引用型別,因此經過引用摺疊,對左值和右值分別產生了左值引用和右值引用,使用remove_reference_t
獲取本來的不帶引用的基本型別,然後static_cast
為對應右值引用型別。
static_cast? 可能心裡想:static_cast能成功嗎?這裡針對右值引用有個特許規則:雖然不能隱式地將乙個左值轉換為右值引用,但是可以用static_cast顯示將乙個左值轉換為乙個右值引用。
再看 forward
// function template forward
template
<
class
_ty>
_nodiscard constexpr _ty&&
forward
(remove_reference_t<_ty>
& _arg)
noexcept
template
<
class
_ty>
_nodiscard constexpr _ty&&
forward
(remove_reference_t<_ty>
&& _arg)
noexcept
也就是說對 **int& 、int&&**都增加了乙個&&,根據引用摺疊規則,其實是沒有改變其引用性質的。
其實這就是模板程式設計不同的地方:回到最初的乙個沒提到的地方,為什麼需要forward(完美**),是因為存在不完美**,也就是如下情況時,對於v而言,不論本身是左值引用還是右值引用,它是乙個有名變數,所以是左值。因此,使用forward將他作為引數傳遞時static_cast
為本來的型別,從而保證引數的正確傳遞。另外一點要理解的是,對於testforward的兩次呼叫,實質上由於引數的不同編譯器產生了兩個不同的函式。
template
<
typename t>
void
testforward
(t && v)
Forward與include的區別
forward與 include 的區別 標籤用於把另外乙個資源的輸出內容插入進當前 jsp頁面的輸出內容之中,這種在 jsp頁面執行時的引入方式稱之為動態引入。從乙個jsp檔案傳遞 request 資訊到另外乙個 jsp檔案,後面的部分將不會被執行。可以使用 傳遞引數。將包含的檔案放在 jsp中和...
forward與include的區別
1 forward指令 forward 指令用於將頁面響應控制 給另外的頁面。既可以 給靜態的 html頁面,也可以 到動態的 jsp 頁面,或者 到容器中的 servlet。jsp 的 forward 指令的格式 第二種語法用於在 時增加額外的請求引數。增加的請求引數的值可以通過httpservl...
forward與direct的區別
今天在群裡面碰到乙個面試失敗的人問 forward與direct的區別,自己想了想也回答不出來,雖然以前也看過這個問題,但老是忘記,現在把與這個問題有關的資料綜合下 1.sendredirect 是向瀏覽器傳送乙個redirect通知,瀏覽器重定向到新的url 位址列的url會改變 forward ...