本文收集一些在C++学习过程中的坑,造成了一些困扰,这些东西比较零碎,现在总结起来,方便各位查阅,也加深下自己的印象。持续更新中…
1,临时对象不可被修改(默认加了const修饰)
class Person{
public:
Person();
Person(Person& p){...}
}
Person getPerson(){
Person p1;
return p1;
}
int main(){
Person p = getPerson();//报错,提示没有对应的构造函数
return 1;
}
因为getPerson()函数返回的是Person类型,所以返回时会创建一个临时对象,然后尝试调用拷贝构造函数赋值给p,但是现在只有一个拷贝构造函数,其参数类型是Person引用类型,所以此时会尝试将getPerson()返回的临时对象绑定到Person&上
Person& 绑定到 临时对象上,又因为C++规定临时对象不可修改,即
左值类型Person&,右值类型const Person,肯定失败,因为引用类型绑定时,必须是可通过改引用来修改的,例如:
int a = 10;
int& b = a; //成功
const int c = 20;
int& d = c; //失败,因为不能通过引用d来修改c的值
想要绑定上,可以把拷贝构造函数形参加个const:
Person(const Person& p){...}
2,C++自定义类型默认提供赋值运算符=的重载,因此p1 = p2才会认为是拷贝
但只是浅拷贝,想实现深拷贝可以自己重写
class Person{
public:
Person(const Person& p){
cout << "拷贝构造函数被调用" << endl;
...
}
void operator=(Person& p){
cout << "operator= 被调用" << endl;
...
}
}
int main(){
Person p1;
Person p2;
Person p3 = p1; //拷贝构造函数被调用,为了区别于下面那行,建议写成Person p3(p1);
p2 = p1; //operator= 被调用
return 1;
}
3,静态成员变量存放在全局数据区
下例中的静态成员变量存放在全局数据区,因此无论Person类还是其对象,占用都是4个字节
并且分配内存的实际不是加载类时,也不是创建对象时,而是执行 int Person::m_B = 20时(初始化的时候)
class Person{
public:
int m_A = 10;
static int m_B;
}
int Person::m_B = 20;
int main(){
Person s1;
cout << sizeof(s1) << endl; //4
cout << sizeof(Person) << endl; //4
}
4,空类及其创建出的对象,内存占用时1个字节
为什么不是0?不应该是NULL吗?对的,是NULL,但是编译器为了区分不同对象所占的空间地址不同,和为了避免除以sizeof(p1)除0的错误,分配了一个字节
但是一旦有其他类继承了空类,并且这个子类不是空的,那么编译器就不会把父类的这1个字节分配给子类
class Person{
}
class Son:public Person{
public:
int m_A = 10;
}
int main(){
Person p1;
cout << sizeof(p1) << endl; //1
cout << sizeof(Person) << endl; //1
Son s1;
cout << sizeof(s1) << endl; //4
return 1;
}
5,typeid关键字
typeid关键字用于获取类型的信息,然后返回的是type_info类型,该类型封装了一些成员函数(比如name函数),
class Person{}
struct Base{}
int main(){
typeid(3);
typeid(int).name() //结果是 int
typeid(double);
typeid(234/23.4);
Person p1;
typeid(p1);
typeid(Base)
return 0;
}