对const对比,const的值允许在运行后确定,但是constexpr不允许
const int a = get_sz();
constexpr int b = get_sz(); // 如果get_sz()不是constexpr函数,则编译出错
比如将字符串赋值给string,由编译器自动执行,但是不能多次
常用于将void*转换成本来的指针类型(由开发者自己保证类型是正确的,否则是未定义的),或者用于基本类型之间的转换
基于更加底层的位模式转换,依赖于机器,应当尽可能避免,其无视任何限制
这种方式,编译器把数组当成指针
void print(const int* p);
void print(const int p[]);
void print(const int p[10]); // 10仅仅是我们期望的,编译器会忽略,均等效与const int*
void print(int & a[10]); // error,这代表数组是10个int 引用,这个不符合语法会编译错误
void print(int (&a)[10]); // ok, a是引用一个大小为10的数组,注意此时,10会被编译器考虑
务必小心括号问题,少括号会产生另外一种语义
void print(int * matrix[10]); // 等效于int ** matrix
void print(int (*matrix)[10]);// 指向一个含有10个元素的数组, 10会被考虑 int (*)[10]
void print(int matrix[][10]);// 与上面等效
void demo(int, int);
using decltype(demo) = Func; // Func是函数类型
using decltype(demo)* = FuncPointer;// 指针类型
Func f(Func g); // error
Func* f(Func g); FuncPointer f(Func g); // ok, 形参里的Func会被转换为函数指针
class A;
class B
{A a; // errorB b; // errorA& c; // okA* d;// ok;static B e; // okstatic A f; // ok
};
注意类里面的友元说明仅仅是声明了访问权限,即便友元函数定义在类内部,也必须在外部声明,否则即便是类的成员函数也无法访问
class A
{
public:friend void f(){cout << "f was called!\n"};void gg(){f();} // error, f还未被声明void hh();
};
void f();
void A::hh(){f();} // ok
此时只能使用new创建对象,且无法delete释放
using可以指示编译器“继承”基类构造函数,这里不是真正的基础,而有编译器自动生成一些构造函数,这些构造函数与基类构造函数有相同的参数列表,如下
derived(pargram):base(pargram)
using不会继承默认、拷贝、移动构造函数
对于含有默认参数的基类构造函数,则会生成多个构造函数,每个构造函数形参数量从最多,依次递减到非默认参数数量
如基类构造函数有两个参数,一个默认,则会生成接受两个参数的和接受左边那个参数的两个构造函数