2017-06-16 23 views
1

我下面這個教程 - http://www.learncpp.com/cpp-tutorial/132-function-template-instances/函數模板,並通過引用的區別

// passing all parameters by references 
template <typename T1, typename T2> 
const T2& add_two_objects(const T1& x,const T2& y) { 
     return x+y; 
}; 

int main() { 
    using std::cout; 
    int x(0),y(0); 
    std::cout << "Please enter number 1" << std::endl; 
    std::cin >> x; 
    std::cout << "Please enter number 2" << std::endl; 
    std::cin >> y; 
    cout<< "sum of two integers is " << add_two_objects(x,y+1.2) << '\n'; 
    cout<< "sum of two double is " << add_two_objects(x,y+2.52424324) << '\n'; 
    return 0; 
} 

程序編譯罰款,但在運行時,我總是得到一個分段錯誤。但是,如果我將模板更改爲按值傳遞,那麼一切正常。

// passing all parameters by value 
template <typename T1, typename T2> 
const T2 add_two_objects(const T1 x,const T2 y) { 
     return x+y; 
}; 

任何人都可以請解釋嗎?

+2

您不能返回到一個臨時的參考。但這是非常無意義的代碼,寫得很差。也許你應該找到一個不同的教程? –

+0

@CodyGray至少turial有'使用std :: cout'而不是使用'namespace std;' – user463035818

+0

我修改了教程示例以嘗試更復雜的事情(當然瞭解)我認爲這個教程非常好。 – infoclogged

回答

6

template <typename T1, typename T2> 
const T2& add_two_objects(const T1& x, const T2& y) { 
     return x+y; 
}; 

返回到一個臨時的參考。讓返回值

template <typename T1, typename T2> 
T2 add_two_objects(const T1& x, const T2& y) { 
     return x+y; 
}; 

你應該沒問題。

順便說一下,不清楚的是,返回T2是在這裏做的最好的事情。考慮例如T1=size_tT2=char的情況。不如歸去的操作x+y實際上產生

template <typename T1, typename T2> 
auto add_two_objects(const T1& x, const T2& y) 
-> decltype(x+y) 
{ 
    return x+y; 
}; 

------ -----編輯

不得引用返回一個臨時對象類型。這是一個錯誤。如果你想要一個bug,那就去做吧。你不應該使用可憐的教程。有時你想/應該返回一個引用,但這不是其中之一。這些參考是指從函數返回時不會被銷燬(或超出範圍)的對象(因爲所有自動和臨時變量都會)。

+0

但我想返回一個參考,而不是您的第一個解決方案建議的值。這是否意味着教程代碼是錯誤的? – infoclogged

+0

@infoclogged你想返回一個參考什麼?在方法範圍內引用一個變量在方法範圍之外沒有用處 – user463035818

+0

好吧,我現在已經明白了。如果我實例化一個靜態對象,那麼引用不再指向一個臨時對象。因此,我可以在函數模板中聲明靜態變量(靜態T2 z;),而不是返回(x + y),然後返回參考(z = x + y; return z;)。當然,這不是一個真正的代碼,只是爲了理解基礎知識。 – infoclogged

1

爲了讓它更清晰讓我們將整數包裹在結構中。

這裏是一個示範項目

#include <iostream> 

struct A 
{ 
    A(int x) : x(x) {} 
    ~A() { std::cout << "[A::~A() is called for x = " << x << ']' << std::endl; } 
    int x; 
}; 

A operator +(const A &lhs, const A &rhs) 
{ 
    return A(lhs.x + rhs.x); 
} 

std::ostream & operator <<(std::ostream &os, const A &a) 
{ 
    return os << a.x; 
} 

template <typename T1, typename T2> 
const T2& add_two_objects(const T1& x,const T2& y) { 
     return x+y; 
}; 

int main() 
{ 
    std::cout<< "sum of two integers is " << add_two_objects(A(1), A(2)) << '\n'; 

    return 0; 
} 

它的輸出可能看起來像

prog.cc:22:18: warning: returning reference to temporary [-Wreturn-local-addr] 
     return x+y; 
       ^
sum of two integers is [A::~A() is called for x = 3] 
Segmentation fault 

所有的編譯器首先警告說,該函數返回引用臨時值。即在退出功能後,臨時對象將被破壞,並且此輸出

[A::~A() is called for x = 3] 

證實了這一點。

結果引用將是無效的,程序有未定義的行爲。

其實你能想象的程序邏輯如下方式

int main() 
{ 
    const A &r = add_two_objects(A(1), A(2)); 
    std::cout<< "sum of two integers is " << r << '\n'; 

    return 0; 
} 

它的輸出看起來在上面的程序

prog.cc:22:18: warning: returning reference to temporary [-Wreturn-local-addr] 
     return x+y; 
       ^
[A::~A() is called for x = 3] 
[A::~A() is called for x = 1] 
[A::~A() is called for x = 2] 
Segmentation fault 

這是參考變爲無效幾乎相同。

如果刪除函數聲明

template <typename T1, typename T2> 
const T2/*&*/ add_two_objects(const T1& x,const T2& y) { 
     return x+y; 
}; 

參考然後程序輸出可能看起來像

sum of two integers is 3 
[A::~A() is called for x = 3] 
[A::~A() is called for x = 1] 
[A::~A() is called for x = 2] 
+0

是否有任何特定的原因,有一個結構的警告,但不是'int's? – user463035818

+0

@ tobi303原因可能是該結構具有構造函數和析構函數。 –