位运算符
#define and &&
#define and_eq &=
#define bitand &
#define bitor |
#define compl ~
#define not !
#define not_eq !=
#define or |
#define or_eq |=
#define xor ^
#define xor_eq ^=
C++没有数字元素是引用的类型
int i, j;
int &array[] = {i, j}; //这样是错误的
注意引用数组的书写,一定要加括号
int a[2];
int &array[2] = a; //错
int (&array)[2] = a;//正确
引用只能建立在同中数据类型上面,但是常引用可以不是同种数据类型
int Max(const int &a,const int &b)
{
return (a>b)?a:b;
}
int main()
{
char c='a';
const int &rc = c; //给c分配了空间
char &rc2 = c;
cout<<(void*)&c<<endl;
cout<<(void*)&rc<<endl;
cout<<(void*)&rc2<<endl;
cout<<Max(rc, 5.5)<<endl<<endl;
int i = 7;
const int &ri = i;
cout<<(void*)&i<<endl;
cout<<(void*)&ri<<endl;
return 0;
}
输出:
0x6afeeb
0x6afeec
0x6afeeb
97
0x6afee4
0x6afee4
在这个程序中,如果将语句const int &rc = c;中的const去掉,将发生编译错误。原因是一般的引用只能建立在相同数据类型的变量上。
同样,之所以允许Max(i, 5.5)这样的函数调用,也是因为函数Ma()的第二个参数是常引用,因此可以将实参5.5先转换为int类型的无名变量,然后再建立对该无名变量的常引用。
所以,对一个表达式建立常引用,如果该表达式的结果可以寻址,并且表达式的数据类型与引用类型相同,那么可以直接将表达式结果的地址送入引用变量。此例中,&i和&ri的值相等就说明了这一点,否则,若是表达式的数据类型与引用类型不相同,或者是表达式结果不可寻址,那么只能另外建立一个无名变量存放表达式结果(或其转换之后的值) ,然后将引用与无名变量绑定,此例中&c与&r的值不相同正好说明了这一点。
为了避免命名空间冲突,可以把名字取地长一些,但是太长不方便书写代码。就可以用变量的形式。
namespace my_new_create_first_space{
void func(){
cout << "Inside second_space" << endl;
}
}
int main ()
{
namespace sp = my_new_create_first_space;
sp::func();
return 0;
}
让全局变量限定在本文件有两种做法
- 加上static
- 用匿名命名空间
但是如果想用全局变量给模板实例化,只能用匿名空间
下面的程序会报错:“&c”不是“char*”类型的有效模板参数,因为“c”没有外部链接
template <char *p>
class example {
public:
void display() {
cout<<*p<<endl;
}
}
static char c = 'a';
int main ()
{
example<&c> a;
a.display();
return 0;
}
此程序不能够通过编译,因为静态变量c不具有外部连接特性,因此不是真正的“全局”变量。而类模板的非类型参数要求用常量类实例化,只有真正的全局变量的地址才能算作常量。为了实现既能保护全局变量(函数)不受重定义错误的干扰,又能够使它们具有外部连妾特性的目的,必须使用匿名名字空间机制。同样是上面这个程序,修改之后如
template <char *p>
class example {
public:
void display() {
cout<<*p<<endl;
}
};
namespace {
char c = 'a';
}
int main ()
{
example<&c> a;
a.display();
return 0;
}
explicit:禁止隐式调用类单参构造函数
禁止类A隐式转换成类B
explicit B(A a) {
}