template
int compare1(const char (&a)[M],const char (&b)[N]){
return strcmp(a,b);
}
int compare2(const char * const &a,const char * const &b){
return strcmp(a,b);
}
int compare3(const char &a,const char *&b){
return strcmp(a,b);
}
int compare4(char * const &a,char * const &b){
return strcmp(a,b);
}
compare1("hello","world"); //right
compare2("hello","world"); //right
compare3("hello","world"); //wrong
compare4("hello","world"); //wrong
compare3错误信息:invalid initialization of non-const reference of type ‘const char&’ from an rvalue of type ‘const char*'
compare4错误信息:deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
我的疑惑:1.模板的const char (&a)[M],const char (&b)[N]这句话是什么意思
2.常量字符串如上面的hello和world只能用const char * const &类型来接收吗?为什么?
3.const char (&a)[M]和const char * const &有什么关系?为什么前者也可以用来接收常量字符串?
4.char ch = 'a';
char *p = &ch;
char *&pch1 = p; //right
char * const &pch2 = p; //right
const char *&pch3 = p; //wrong
const char * const &pch4 = p; //right
为什么const char *&pch3 = p;会出错
抱歉,引用和指针组合,确实有一些,令人困惑之处。
刚刚实验一下,不一定每个编译器都这样,
字符串字面值,和指针,指针引用参数状况:
const char *const 这个好理解
const char *const & 这个也好理解
const char *& ///抱歉,不能匹配,因为指针不是常量,所以这种指针的引用,不能匹配字符串字面值
const char * ///这个也好理解
char * & ///抱歉,不能匹配,因为指针不是常量,所以这种指针的引用,不能匹配字符串字面值
char * /// 可以匹配 ,兼容?
数组引用,和字符串字面值:
char(&)[6] 和“Hello” 不匹配 ,字符串字面值 是常量字符串,其每个元素都是常量。
const char (&)[6]; 和“Hello” 匹配
1,是数组的引用,const修饰数组内容
2,可以使用const char *&接收,第二个const修饰引用指针,还可以不要&
非模板数组引用,数组的元素个数只能是固定的
“hello” 是 数组常量
第一个就是一个模板,这个模板的参数是非模板参数也就是说他不是一个类似于typename T这种的模板参数,在编译器编译的时候你传入了两个常量数组他会根据这两个数组的大小去初始化N和M至于参数为啥是指向数组的引用,这个或许想在函数里面改这个数组或许是节约内存,反正就跟一般的引用传值一样的好处。
第二个不一定用你说的那个类型来接受,只要保证是一个指向常量的变量就行了,因为你的常量字符串就是一个常量,常量字符串不能转换为非常量。所以只要保证const char*就好。后面的只是保证char是一个常量和引用传值,这个引用传值上一个问题已经说过同样的道理。
第三个,一个是数组一个是指针M是数组大小,同样是引用传值,都能用来接受常量字符串前面一个问题已经说过了只要保证const char就行,这个表示的就是指向常量的数组或者指针对于你这个来说的。
第四个前面的也能说明问题其实你只要搞懂指向常量的指针和常量指针你就清楚了。前面的几个也一样。由于是手机所以不好一一说清楚每次都只有提交了才看下一个问题哈。
一、函数模板
一个通用的函数模板(function template)就是一个公式,可用来生成针对特定类型或特定值的函数版本。模板定义以关键字template开始,后面跟一个模板参数列表,列表中的多个模板参数(template parameter)以逗号分隔。模板参数表示在类或函数定义中用到的类型或值。
1、类型参数
一个模板类型参数(type parameter)表示的是一种类型。我们可以将类型参数看作类型说明符,就像内置类型或类类型说明符一样使用。类型参数前必须使用关键字class 或typename:
template // typename和class一样的 T function(T* p) { T tmp = *p; // 临时变量类型为T //... return tmp; // 返回值类型为T }
关键字typename和class是一样的作用,但显然typename比class更为直观,它更清楚地指出随后的名字是一个类型名。
编译器用模板类型实参为我们实例化(instantiate)特定版本的函数,一个版本称做模板的一个实例(instantiation)。当我们调用一个函数模板时,编译器通常用函数实参来为我们推断模板实参。当然如果函数没有模板类型的参数,则我们需要特别指出来:
int a = 10; cout << function(&a) << endl; // 编译器根据函数实参推断模板实参 cout << function(&a) << endl; // 指出模板参数为int
2、非类型参数
在模板中还可以定义非类型参数(nontype parameter),一个非类型参数表示一个值而非一个类型。我们通过一个特定的类型名而非关键字class或typename来指定非类型参数:
// 整形模板 template void add() { cout<< M+N << endl; } // 指针 template void func1(const char* str) { cout << C << " " << str << endl; } // 引用 template void func2(const char* str) { cout << R << " " << str << endl; } // 函数指针 template void func3(const char* c) { f(c); } void print(const char* c) { cout << c << endl;} char arr[9] = "template"; // 全局变量,具有静态生存期 int main() { add(); func1("pointer"); func2("reference"); func3("template function pointer"); return 0; }
当实例化时,非类型参数被一个用户提供的或编译器推断出的值所替代。一个非类型参数可以是一个整型,或者是一个指向对象或函数的指针或引用:绑定到整形(非类型参数)的实参必须是一个常量表达式,绑定到指针或引用(非类型参数)的实参必须具有静态的生存期(比如全局变量),不能把普通局部变量 或动态对象绑定到指针或引用的非类型形参。
我的疑惑:1.模板的const char (&a)[M],const char (&b)[N]这句话是什么意思
2.常量字符串如上面的hello和world只能用const char * const &类型来接收吗?为什么?
3.const char (&a)[M]和const char * const &有什么关系?为什么前者也可以用来接收常量字符串?
4.char ch = 'a';
char *p = &ch;
char *&pch1 = p; //right
char * const &pch2 = p; //right
const char *&pch3 = p; //wrong
const char * const &pch4 = p; //right
为什么const char *&pch3 = p;会出错
上面的模板是整形模板,下来呢① int compare1(const char (&a)[M],const char (&b)[N]){__
return strcmp(a,b);
}
其中如const char (&a)[M]是数组引用,对比着数组指针理解就可以了...②不是的,只要你的形参的达到常量字符串类型的要求就可以
,但是一般为了安全性,会加const,看代码:
//int compare2(const char * const &a,const char * const &b){
//int compare2(const char * const a,const char * const b){
//int compare2(const char * a,const char * b){
int compare2(const char * const &a,const char * const &b){
return strcmp(a,b);
}我注释的都可以正确运行的...③ 理解这个问题,首先你必须了解一个问题,就是引用的底层实现还是内存寻址,也就是说编译器对他解析所
干的事跟解析指针所执行的步骤是一样的,因为他就是c++标准对指针的进一步封装,理解吧,所以这个问题你就可以将引用理解为指针来用
具体细节你仔细思考就可以理解,学底层的东西就是要不断的去思考,不是吗?④ 如果你理解了我说的,那第四个问题就太过基础了吧..呵呵
4646545646456645