预处理命令:存在于xxx.h文件中

#ifndef  //防止重复包含

#define  //定义

#endif  //结束

头文件中不加上预编译指令,造成的重复定义是编译期错误。

在实际操作过程中,一般不在头文件中定义变量。

某些函数不是为了提供给用户,而是只针对某个其他函数使用,此时不应该把这些函数的声明放在头文件中,而是直接在头文件对应的源文件中定义。反映在C++的类定义中,这些函数应该设为私有。

类型转换:

若表达式中有double 类型,则结果也为doublefloat),若都为int型,做除法运算时会丢失小数部分.

强制类型转换 :()a    c++: static_cast< 类型>(变量);

指针:

指针第1个含义是指向的内存的基地址,第二个含义是本身的类型  

   int c = 5;

   int *a = &c;

 a 是一个指向int类型的指针,a中存放的是c的地址,&是取址符

声明和赋值

 int c = 5; //声明初始化

 int c;

 c = 5;//赋值

变量声明,函数声明;

  1. //正确的交换函数
  2. int swap(int *a,int *b)   //*a 和 *b 是声明,下文的 ab指的是两个int型指针;
  3. {    
  4. int temp=*a;    //*是取值操作
  5. *a=*b;         //将 ab变量对应的内容交换
  6. *b=temp;

  7. C++中,初始化和赋值是两个不同的概念。比如:
  8. //初始化一个string类的对象,初始值为helloworld
  9. string str1("helloworld");
  10. //错误,初始化的一个空对象,不能像初始化那样赋值
  11. string str2;
  12. str2("helloworld);
  13. //正确,初始化的一个空对象,利用符号重载后的“=”进行赋值
  14. string str3;
  15. str3 = "helloworld";
  • 很多操作中,只是通过复制一个副本来进行,就像函数传参中的值传递一样。比如:
  1. //从左到右,先将str1连接到str中,然后再将,str2连接到str的尾部。但str1str2中的值未变
  2. string str, str1, str2;
  3. str = str1 + str2;
  4. //这里只是将str的一个副本复制到vec
  5. vector<string> vec;
  6. string str(helloworld);
  7. vec.push_back(str);

 

//错误的申请一维动态数组的函数

 

  1. #include <stdio.h>
  2. void test(char *s)
  3. {    
  4. s=malloc(1000);    
  5. //形参s的初始值为NULLmalloc后为堆上一块区域的首址,此时,实参中指针的值没变化,所以函数结束后,实参指针申请失败,函数传递的本质是值传递,我们要改变的是实参的内容,而不是指向实参的内容。
  6. }
  7. //两种正确写法void test(char **s)   //实参是个指针,形参是个指针的地址
  8. {    
  9. *s=malloc(1000);  //改变实参的内容
  10. }
  11. char *test(char *s)
  12. {    
  13. s=malloc(1000);    
  14. return s;
  15. }
  16. int main(int argc,char *argv[])
  17. {    
  18. char *s=NULL;    
  19. //传入函数的是s的副本,是一个临时变量,也是局部变量,是指针变量的值拷贝,即两个指针变量的值一样。所已要在函数中改变一个变量,要把这边变量的地址传进去。*xx只是一个语义的写法,是个声明    
  20. test(s);    
  21. return 0;
  22. }

动态分配内存 

int *p = (int*)malloc(sizeof(int) *10)); 

sizeof(int) 是一种跨平台的做法

malloc 返回的实void* 需要强制类型装换 

New 的三种申请方法

1 int *p = new int;

2 int *p = new int(10);

3 int *p = new int[10];

malloc 和 new的区别:

new是运算符,malloc是函数

new会执行某些类型的构造函数,而malloc仅仅申请内存。

所以对于string类型,只可以使用new,绝对不可以使用malloc!!

常见的异常有:

exception 最常见的问题

out_of_range 越界错误

invalid_argument 非法参数

千万不要返回局部对象的引用或者指针!!!

例如:

const std::string &manip(const std::string &s)

{

std::string ret = s;

return ret;

}

上例中的ret是个局部对象,离开这个函数后就被销毁了,此时函数返回一个它的引用,实际上是引用了一块非法的内存区域。

 

动态开辟一个二维数组 3*4 的思维首先使用一个二重指针,二重指针开辟三个一重指针的空间每个一重指针再开辟4个空间

  1. int **arr=(int **)malloc(3*sizeof(int*));
  2. for (int i=0;i!=3;i++)
  3. {    
  4. arr[i]=(int *)malloc(4*sizeof(int));
  5. }

释放空间的过程与分配动态空间的过程刚好相反:

  1. for (int i=0;i!=3;i++)
  2. {    
  3. free[arr[i]);
  4. }
  5. free(arr);

这种动态分配的数组可以直接用 void print(int **array)进行传参。

函数指针  void (*函数指针名字)(int, int)

内存泄露 内存分配使用后,并没有回收,导致失去了分配的那片内存的控制方式

值传递、地址传递、引用

  • 值传递是指在函数传参过程中,复制一个副本给函数的形参,实参和形参的值相同,但问题是,一旦形参发生改变,则不会作用到实参上。解决方法为,地址传递或引用,或通过返回值来传递修改后的值。
  • 地址传递是指在函数传参过程中,传递的是变量的地址,实质上仍是值传递,传递的是指针的值,即变量的地址。
  • 引用是指给变量起了一个别名。在C++中,对于传值操作,一般用引用而不用指针。同时,注意要根据是否要改变实参值而判断是否要用const来修饰。

声明常量时要初始化,对变量最好也先初始化

输入/输出流  istream 和 ostream 都是有缓冲区的 作为形参时不能为const

宏函数和内联函数的区别:

宏函数是在预编译期间进行替换。

内联函数是在编译期间进行代码扩展。

内联函数可以看做高级的宏函数,它进行语法检查。

宏函数只要不进行调用,就不会产生语法检查,而内联函数必须首先经过严格的语法检查才能进行代码扩展.

/*

 * 这里在返回int时生成了一个无名的int值

 * 这是一个临时的值

 */

int get_val(){

    int a = 2;

    return a;

}

 

 

int main(int argc, const char *argv[])

{

    cout << get_val() << endl;

    //a的值赋予返回的中间值,然后赋值给res

    int res = get_val();

    return 0;

}

 

static数据成员

  • static数据成员没有this指针,它直属于这个类,也即所有这个类的对象共享这个数据成员。非static数据成员隶属于这个类的各个对象,也即各个对象都独自拥有这个数据成员。
  • 它并不是真正意义上的全局变量,作用域仅仅为这个类。
  • static数据成员必须在类的外部定义,不像普通数据成员那样通过构造函数来进行初始化的。
  • static成员函数没有this指针,原因同上。
  • static成员函数不能被声明为const,因为static成员函数是直属于类,而非对象,而成员函数声明为const就是承诺不会修改该函数所属的对象,两者矛盾。
  • 可以通过作用域从类直接调用static成员函数,当然也可像普通成员函数那样,通过对象、对象的引用、指向该类类型的对象的指针间接。
  • static成员函数只能对static数据成员进行操作,因为static成员函数是直属于这个类的,而非static数据成员是直属于对象的,若它对一些非static数据成员进行操作,会影响对象的非static数据成员的安全。

static成员函数

static成员函数能够对static数据成员和非static数据成员进行操作