2012-11-25 10 views
12

Sto seguendo il Pluralsight C++ corso, e in essa è il seguente codice:non in grado di convertire il parametro da 'int' a 'int &'

#include <iostream> 

template <class T> 
T max(T& t1, T& t2) 
{ 
    return t1 < t2 ? t2 : t1; 
} 

int main() 
{ 
    std::cout << "Max of 33 and 44 is " << max(33, 44) << std::endl; 

    return 0; 
} 

ho digitato su questo pezzo di codice, ma a differenza del codice di del corso, mi appare un messaggio di errore:

C2664: 'max' : cannot convert parameter 1 from 'int' to 'int &' 

il codice del corso è scritto in Visual Studio Express 2010, mentre la mia è scritto in Visual Studio Ultimate 2010.


EDIT

Grazie a tutti (anche a Kate Gregory stessa) per aver fornito risposte e chiarito tutto.

+0

Avete un collegamento al corso ed è il codice _exact_ del corso? –

+0

Il corso si chiama Fondamenti di Pluralsight C++, la prima parte. È il codice esatto C'è anche un codice che usa max con le stringhe e una classe definita dall'utente, ma non ha nulla a che fare con gli interi che vengono passati in max, mostrando solo la funzionalità di max. –

risposta

30

Poiché i valori letterali (e i valori di riferimento in generale) non possono essere passati con riferimento non const (poiché non avrebbe senso se il destinatario potesse modificarli).Sia passano valore o per riferimento const:

template <class T> 
T max(const T& t1, const T& t2) 
{ 
    return t1 < t2 ? t2 : t1; 
} 

o

template <class T> 
T max(T t1, T t2) 
{ 
    return t1 < t2 ? t2 : t1; 
} 
3

Non è possibile passare il valore temporaneo come T&. Dal momento che non si cambia argomento, utilizzare const T& invece

BTW, non v'è built-in max funzione

+0

Sì, dicono nel corso che c'è un max. È una semplice demo che mostra come utilizzare un modello. –

2

Se avete definito la vostra funzione con parametri per riferimento, non è possibile utilizzare qualsiasi cosa, ma i nomi di variabile per detti parametri - e tu provi a usare i numeri.

4

Entrambi i numeri 33 e 44 sono valori limite; vengono passati alla funzione in base al valore e non in base al riferimento. Il compilatore non può convertire questi due nel tipo previsto int &. Utilizzare le variabili (lvalue) in quanto possono essere passati per riferimento:

int a = 33, b = 44; 

max(a, b); // 44 

Dal momento che si sta semplicemente fare con tipi fondamentali qui (int), passando per riferimento è superfluo. Passare per valore causa una copia, ma la differenza sarà trascurabile:

template <class T> 
T max(T t1, T t2); 

Qui possiamo passare sia rvalues ​​che lvalue. Ma lo è la possibilità che tu possa passare in un oggetto di tipo classe. In tal caso si consiglia di passare per riferimento.

Ma per il caso in cui non vogliamo una copia e vogliamo sia lvalue e rvalues, si può passare da const di riferimento:

template <class T> 
T max(T const &t1, T const &t2); 

In C++ 11 è possibile passare gli argomenti da un universal-riferimento in modo che si può legare glvalues:

template <class T> 
T max(T&& t1, T&& t2); 

int main() 
{ 
    int a{0}, b{0}; 

    max(a, b); 
    max(1, 2); 
} 

Se si desidera mantenere la sintassi lvalue riferimento nel codice originale, è possibile utilizzare questo valore assegnabile spessore:

template<typename T> 
T& lvalue(T&& t) 
{ 
    return t; 
} 

int main() 
{ 
    max(lvalue(1), lvalue(2)); 
} 
3

letterali interi non possono essere passate come riferimento non-const. Inoltre, la funzione max può lavorare con const riferimenti, in modo da segnare in modo appropriato:

T max(const T& t1, const T& t2) 
4

La risposta qui risulta risiedere nel codice di estranei non è stato utilizzato nel test. Assolutamente il mio piccolo max() dovrebbe prendere o per valore, o const-ref, e quello era solo un brain-slip che sistemerò il prima possibile.

Ma il codice demo completo funziona magnificamente. Questo perché include più intestazioni, una delle quali introduce xutility e quindi std::max. Questo mi ha portato a non notare che il mio max non era in uso. Ripeterò la demo con un nome come biggest per eliminare il problema. E nel frattempo, sì, se vuoi passare letterali a una funzione per riferimento, devono essere const ref. Lo sapevo, ma non ci pensavo mentre scrivevo l'imbracatura di prova, e poi sono stato ingannato quando il codice errato sembrava funzionare. Dovrei rileggere il codice con più attenzione: grazie per averlo chiamato alla mia attenzione. (E grazie per aver seguito il corso e spero lo troviate utile.)

+1

:-) Grazie mille per la tua risposta! E sì, trovo il corso utile. Ho usato C# per alcuni anni, e ho sempre voluto provare il C++ ma era ... spaventoso? Il corso mi ha fatto entrare facilmente. –

+1

Il problema di chiamare accidentalmente 'std :: max' invece del proprio' max' è possibile solo con un 'using namespace std;' da qualche parte nel proprio codice. [Sappiamo che questa è una pessima idea] (http://stackoverflow.com/questions/1452721/). Vergognatevi! ;) – fredoverflow

+1

:-) è una cattiva idea in un file di intestazione - questo dimostra che può morderti anche in un file .cpp. –

2

Piccola osservazione. È possibile utilizzare il codice iniziale della funzione "max". Prova a cambiare chiamata da max(34, 44) a max<const int>(34,44). A volte può essere utile.

#include <iostream> 

template <class T> 
T max(T& t1, T& t2) 
{ 
    return t1 < t2 ? t2 : t1; 
} 
int main() 
{ 
    std::cout << "Max of 33 and 44 is " << max<const int>(33, 44) << std::endl; 
    return 0; 
} 
+0

Non ho ancora incontrato quello. Grazie. –