C++总结体会
Posted lzy820260594
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++总结体会相关的知识,希望对你有一定的参考价值。
摘要:本文主要记录了在复习c++过程中的体会。
1、关于const
- 在c++中,const代表的是一种只读权限,即代表变量的值不可以再修改;
- 相比define而言,const修饰的数据可以有类型,更加地注重作用域;
- const修饰的变量用基础数据类型进行初始化时,只会标记到符号表,而不会分配内存;用变量名来进行初始化时,会分配内存;当const修饰的变量是一个自定义的数据类型时,那么也会分配内存;
- 只要进行了内存的分配,那么就可以通过指针的方式进行修改;
- 在c语言中const修饰的变量默认跨文件;而c++中的const修饰的变量默认作用于本文件,如果要实现跨文件,那么就应该借助extern;
2、关于typedef
- typedef可以用于给数据类型起别名:typedef int size,那么就可以用size来定义int型数据;
- typedef可以用于给某一个数组类型起别名:typedef int Arry[10],那么就可以用Arry来直接定义一个元素个数为10的int型的数组:Arry buff=.......;
- typedef可以给一个指针类型起别名:typedef int * ptr,那么就可以直接用ptr来定义一个指针:ptr p相当于int * p;
3、关于引用reference
- 变量本质上就是某一个内存空间的代号,而引用本质上就是这个内存空间的代号2、代号3.......,所有的代号在本质上都一样,完全等价;
- 在定义一个变量时可以不对其进行初始化:int a;但是定义一个引用时则必须进行初始化:int &b=a;这是因为既然起别名就要知道是为谁起别名,否则就没有意义,而被起别名的这段空间也必须是明确的才可以,正如我们给一个人起外号,必须要知道这个人是谁,我们不能说给某人起外号,给一个不知道的人起外号这都是没有意义的,所以引用不可以用于NULL;
- 对一个单一的变量建立引用是及其简单的,而给一个数组建立引用可以采用两种方式:第一种是借助typedef(typedef int Arry[10];Array &buff=arr;这里的arr是一个数组名);第二种是要将&buff括起来,表示数组名的引用(int (&buff)[10]=arr);
- 引用是通过指针常量来实现的(type * const ref=&val);这里的const是说明ref这个指针只可以指向val的空间,而不能指向其他的地址,这也就是为一个别名不能用于多个变量的实现原理;
- 对于指针的引用,在设置形参时,我们可以用二级指针的形式来表示 **p ,也可以直接用引用来表示 *&p;
- 常量引用const type &b=a;这里运用const的意思是不希望通过引用的方式将变量的值改变,多数应用在传参的过程中,不希望操作形参时将实参改变了;
关于指针的引用,这里加入一段代码,帮助理解:
1 #include<iostream> 2 3 using namespace std; 4 5 struct Teacher 6 7 int age; 8 ; 9 10 void AgeChange(Teacher **teacher) //这里的形参采用的是二级指针的方式 11 *teacher = new Teacher; 12 (*teacher)->age = 10; 13 14 void Age_Change(Teacher *&teacher) //这里的形参就是一个引用 15 teacher->age = 100; 16 17 18 int main() 19 Teacher *MrLiu=NULL; //定义一个指针变量 20 21 AgeChange(&MrLiu); //根据形参要求,这里传入的是指针的地址 22 cout << (*MrLiu).age << endl; 23 24 Age_Change(MrLiu); 25 cout << (*MrLiu).age << endl; 26 27 delete MrLiu; 28 29 system("pause"); 30 return 0; 31
4、关于extern"C"
在c++编译环境中,程序编译后,会发生函数的重载。而在c语言中并不会发生函数的重载,也就是说,当我们在c++环境中去调用c语言模块下的函数时,由于c++连接器会寻找重载后的函数,这当然是找不到的,那么此时就需要用到extern"C"。具体实现如下:
MyModule.h
1 #ifndef MYMODULE_H 2 #define MYMODULE_H 3 4 #include<stdio.h> 5 6 #if __cplusplus 7 extern "C" 8 #endif 9 10 void func1(); 11 int func2(int a,int b); 12 13 #if __cplusplus 14 15 #endif 16 17 #endif
MyModule.c
1 #include"MyModule.h" 2 3 void func1() 4 printf("hello world!"); 5 6 int func2(int a, int b) 7 return a + b; 8
TestExternC.cpp
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 using namespace std; 4 5 #if 0 6 7 #ifdef __cplusplus 8 extern "C" 9 #if 0 10 void func1(); 11 int func2(int a, int b); 12 #else 13 #include"MyModule.h" 14 #endif 15 16 17 #endif 18 19 #else 20 21 extern "C" void func1(); 22 extern "C" int func2(int a, int b); 23 24 #endif 25 26 int main() 27 func1(); 28 cout << func2(10, 20) << endl; 29 return EXIT_SUCCESS; 30
5、关于class和struct
struct就是一个public权限下的class。
6、关于拷贝构造函数
有三种情况会调用拷贝构造函数:
- 用旧对象初始化新对象;
- 函数的形参是普通的对象,进行值传递会调用拷贝构造函数;
- 函数的返回值是一个普通的对象;
7、关于构造函数的调用
- 如果在一个类中,用户不写任何一个构造函数,那么系统默认会提供无参构造函数、析构函数、拷贝构造函数;
- 如果在一个类中,用户写了拷贝构造函数,那么系统就不再提供任何一种构造函数;
- 如果在一个类中,用户写了非拷贝构造的构造函数,那么系统不会再提供无参构造函数,但是依然会提供默认构造函数;
8、关于深拷贝和浅拷贝
我们知道,直接将一个对象赋值给另一个对象,这样的拷贝就是浅拷贝。如果被拷贝的对象里面只有基本的数据类型,那么这样的拷贝无非就是数据的相互赋值,完全没有问题。但是如果类中含有指针变量,指针变量在定义的时候是需要指向一段地址的,也就是说需要从堆中拿出一块内存,那么在这个指针进行拷贝的时候,会把这个指向的内存空间也进行拷贝;在堆中获取了空间以后,是需要释放的,那么在两个对象都被释放的时候,同一段内存就被释放了两次。这样就是违法的,会导致程序执行的崩溃,这也就是浅拷贝的弊端所在。
下面的例子就是浅拷贝:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 4 using namespace std; 5 6 class Person 7 public: 8 Person() 9 10 Person(const char *name) 11 m_name =(char*)malloc(strlen(name)+1); 12 strcpy(m_name,name); 13 14 ~Person() 15 if (m_name!=NULL) 16 17 cout << "析构函数调用" << endl; 18 free(m_name); 19 20 21 private: 22 char *m_name; 23 ; 24 void test() 25 Person p1("abc"); 26 Person p2(p1); //系统自带的默认拷贝构造函数,直接崩溃,属于浅拷贝 27 28 29 int main() 30 test(); 31 32 system("pause"); 33 return 0; 34
而所谓深拷贝,就是要避免浅拷贝存在的弊端,为新的对象创建新的空间,然后再进行拷贝,这样就不会导致同一段内存被释放两次。具体如下:
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 4 using namespace std; 5 6 class Person 7 public: 8 Person() 9 10 Person(const char *name) 11 m_name =(char*)malloc(strlen(name)+1); 12 strcpy(m_name,name); 13 14 Person(const Person &person) //自定义的拷贝构造函数 15 m_name = (char*)malloc(strlen(person.m_name)+1); 16 strcpy(m_name,person.m_name); 17 18 ~Person() 19 if (m_name!=NULL) 20 21 cout << "析构函数调用" << endl; 22 free(m_name); 23 24 25 private: 26 char *m_name; 27 ; 28 void test() 29 Person p1("abc"); 30 Person p2(p1); //拷贝构造函数 31 32 33 int main() 34 test(); 35 36 system("pause"); 37 return 0; 38
9、关于explicit
explicit主要是防止隐式转换。
以上是关于C++总结体会的主要内容,如果未能解决你的问题,请参考以下文章