标签:
预处理命令:存在于xxx.h文件中
#ifndef //防止重复包含
#define //定义
#endif //结束
头文件中不加上预编译指令,造成的重复定义是编译期错误。
在实际操作过程中,一般不在头文件中定义变量。
某些函数不是为了提供给用户,而是只针对某个其他函数使用,此时不应该把这些函数的声明放在头文件中,而是直接在头文件对应的源文件中定义。反映在C++的类定义中,这些函数应该设为私有。
类型转换:
若表达式中有double 类型,则结果也为double(float),若都为int型,做除法运算时会丢失小数部分.
强制类型转换 c :()a c++: static_cast< 类型>(变量);
指针:
指针第1个含义是指向的内存的基地址,第二个含义是本身的类型
int c = 5;
int *a = &c;
a 是一个指向int类型的指针,a中存放的是c的地址,&是取址符
声明和赋值
int c = 5; //声明初始化
int c;
c = 5;//赋值
变量声明,函数声明;
- //正确的交换函数
- int swap(int *a,int *b) //*a 和 *b 是声明,下文的 a,b指的是两个int型指针;
- {
- int temp=*a; //*是取值操作
- *a=*b; //将 a和b变量对应的内容交换
- *b=temp;
- }
在C++中,初始化和赋值是两个不同的概念。比如:
- //初始化一个string类的对象,初始值为helloworld
- string str1("helloworld");
- //错误,初始化的一个空对象,不能像初始化那样赋值
- string str2;
- str2("helloworld);
- //正确,初始化的一个空对象,利用符号重载后的“=”进行赋值
- string str3;
- str3 = "helloworld";
- 很多操作中,只是通过复制一个副本来进行,就像函数传参中的值传递一样。比如:
- //从左到右,先将str1连接到str中,然后再将,str2连接到str的尾部。但str1与str2中的值未变
- string str, str1, str2;
- str = str1 + str2;
- //这里只是将str的一个副本复制到vec中
- vector<string> vec;
- string str(helloworld);
- vec.push_back(str);
//错误的申请一维动态数组的函数
- #include <stdio.h>
- void test(char *s)
- {
- s=malloc(1000);
- //形参s的初始值为NULL,malloc后为堆上一块区域的首址,此时,实参中指针的值没变化,所以函数结束后,实参指针申请失败,函数传递的本质是值传递,我们要改变的是实参的内容,而不是指向实参的内容。
- }
- //两种正确写法void test(char **s) //实参是个指针,形参是个指针的地址
- {
- *s=malloc(1000); //改变实参的内容
- }
- char *test(char *s)
- {
- s=malloc(1000);
- return s;
- }
- int main(int argc,char *argv[])
- {
- char *s=NULL;
- //传入函数的是s的副本,是一个临时变量,也是局部变量,是指针变量的值拷贝,即两个指针变量的值一样。所已要在函数中改变一个变量,要把这边变量的地址传进去。*xx只是一个语义的写法,是个声明
- test(s);
- return 0;
- }
动态分配内存
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个空间
- int **arr=(int **)malloc(3*sizeof(int*));
- for (int i=0;i!=3;i++)
- {
- arr[i]=(int *)malloc(4*sizeof(int));
- }
释放空间的过程与分配动态空间的过程刚好相反:
- for (int i=0;i!=3;i++)
- {
- free[arr[i]);
- }
- 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数据成员进行操作
c++基础
标签:
原文地址:http://www.cnblogs.com/jerrmylei/p/4454341.html