C++中的模板中引用的问题

# include <iostream># include <typeinfo>
using namespace std;
template <typename T, typename U>
struct Pair
{
T first;
U second;
Pair():first(), second(){}
Pair(const T& a, const U& b):first(a), second(b)
{
cout << "typeid(T).name():" << typeid(T).name() << endl;
cout << "typeid(U).name():" << typeid(U).name() << endl;
}
};
template <typename T, typename U>
ostream& operator<<(ostream& o, const Pair<T, U>& p)
{
return o << p.first << ':' << showpoint << p.second;
}
template <typename T, typename U>个
/*********************这里不能够加引用, 加上会出错, 请问为什么??*****************/
Pair<T, U> mp(const T& f, const U& s)
{
return Pair<T, U> (f, s);
}
int main()
{
cout << Pair<int, double>(20, 1.782) << endl;
//这样识别太麻烦我写了一个函数模板来实现
cout << mp(12, 2.0) << endl;//使用引用没有问题
cout << mp("hello", 19) << endl;//使用引用有问题, 为什么??
cout << typeid("hello").name() << endl;
return 0;
}

1 不能加引用
这里的代码是 return Pair<T, U> (f, s)。
Pair<T, U> (f, s)是调用构造函数生成一个匿名对象。这个对象是语法临时生成。这类临时性质的匿名对象是不允许加引用的。
例如:
Pair<int, double> a =Pair<int, double>(20, 1.782); //允许。
Pair<int, double>& a =Pair<int, double>(20, 1.782); //不允许。

2 cout << mp("hello", 19) << endl;//使用引用有问题, 为什么??
所有模版是进行类型展开。
“hello”属于静态常量,其类型是char[6]。
我们把代码做语法展开,数组的引用?char[6]的引用如何表示???
语法上基本类型的数组根本没有引用这种语法。

所以这里可以改成字符传对象来处理:
cout << mp(string("hello"), 19) << endl;追问

为什么不加引用可以正确执行呢?不加引用他的类型还是char [6]的啊!他是如何执行的啊??

追答

一般加引用,是希望直接返回对象内部的某个成员(同时可减少一次拷贝构造)。或返回函数参数中的参数,能够让操作符或函数连写。加不加引用和是否可执行没有关系。

模版技术不是动态执行的。而是在编译的时候,根据调用情况,进行语法展开。展开出实际代码再编译其代码形成最终程序。

追问

我明白加引用的含义是为了直接使用我的意思是我将引用去掉之后他就可以正确的执行了!只是为什么?“?

追答

引用只能引用在有名变量上。
不能使用在匿名变量上。

这里的Pair (f, s);就是生成一个匿名对象。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-04-10
我也没遇到过这种问题,不过,应该是字符串的转换问题,"hello"被当做是字符数组了,
因为模板的匹配的时候,如果存在改类型是不会转换成别的类型的,
mp("hello", 19) 就相当于mp<char[6],int>("hello", 19) 了,而不是mp<string,int>("hello", 19)

Pair<T, U> mp(const T& f, const U& s)
{
return Pair<T, U> (f, s);
}
这里的f是一个char[6]类型了, 调用Pair<T, U> (f, s);的时候 f是作为一个字符数组来初始化first

很明显数组直接赋值初始化,是不正确的

解决办法
1. 给hello套上string 即 mp(string("hello"), 19);
2. 显式调用 mp<string,int>("hello", 19)

建议:不要把c的常字符串当做是string ,虽然他们可以互相转换
相似回答