5. C++内存分配与释放浅析(以后会深入讲解更新)
我们一般以一下的形式对C++进行内存配置和释放。
class Foo{ };
Foo *pf = new Foo; // 配置内存,然后构造对象
delete pf; //将对象析构,然后释放对象
其中 new算式内含两个阶段操作 :
(1)调用::operator new操作符配置内存
(2)调用Foo::Foo()构造对象内容
delete算式也包含两个阶段操作:
(1)调用Foo::~Foo()将对象析构
(2)调用::operator delete释放内存
如果我们想要创建对象的时候初始化可以用如下形式:
string *ps = new string("Hello"); // *ps is "Hello"
与malloc和free的区别
(1)new/delete调用 constructor/destructor.Malloc/free 不会
(2)new 不需要类型强制转换。.Malloc 要对放回的指针强制类型转换.
(3)new/delete操作符可以被重载, malloc/free 不会
(4)new 并不会强制要求你计算所需要的内存 ( 不像malloc)
6. C语言数组与字符串
1. 数组的定义与初始化
在数组定义时,如果没有显式提供元素初值,则数组元素会像普通变量一样初始化:
在函数体外定义的内置数组,其元素均初始化为0;
在函数体内定义的内置数组,其元素无初始化
不管数组在哪里定义,如果元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显式初始化.
2. 特殊的字符数组
字符数组有两种初始化方式
(1) 用一组由花括号括起来、逗号隔开的字符字面值进行初始化。
(2) 用一个字符串字面值进行初始化。
两种初始化形式有所不同。第(2)种初始化方式包含一个额外的空字符(null)用于结束字符串。举例如下:
char ca1[ ] = {‘C’, ‘+’, ‘+’}; // no null
char ca2[ ] = {‘C’, ‘+’, ‘+’, ‘\0’}; // explicit null(也可以写为{‘C’, ’+’, ‘+’, 0 })
char ca3[ ] = “C++”; // null added automatically
上例中ca1的维数为3, ca2和ca3的维数为4
注: strlen计算字符串的大小时从字符串开头直到遇到null为止,在计算strlen(ca1)时结果是未知的。原因是不知道何时会遇到null 而strlen(ca2)与strlen(ca3)的结果都将是3
3. string s(n, ‘c’) // 将s4初始化为字符 ’c’的n个副本
vector<T> v(n, i); // v 包含n个值为i的元素
vector和string中计算大小建议使用size_type类型,因为它与机器无关,不建议使用int类型。
4. vector类型的值初始化
vector中如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行值初始化。例如:
l 如果vector保存内置类型(如int)的元素,那么标准库将用0值创建元素初始化式:
vector<int> fvec(10); // 10 elements, each initialized to 0
l 如果vector保存的是含有构造函数的类类型的元素,标准库将用该类型的默认构造函数创建元素初始化式:
vector<string> sevc(10); // 10 elements , each an empty string
5. vector 下标操作不添加元素
vector<int> ivec ; // empty vector
for(vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; //disaster: ivec has no elements
在上例中ivec是空的vector对象,而下标只能用于获取已经存在的元素。
正确的写法应该是
for(vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec.push_back(ix);
7. volatile变量
volatile变量有两个作用:一个是告诉编译器不要进行优化;另一个是告诉系统始终从内存中取变量的地址,而不是从缓存��取变量的值以免读取脏数据
8. vector和map进行下标操作时的区别vector下标操作不产生新元素,map进行下标操作的话如果没有新元素会插入到map
9. 深拷贝与浅拷贝
浅拷贝其实只是复制对象,而不复制它引用的对象。即,拷贝对象的所有变量都含有被拷贝对象所含有的值,而且拷贝对象对其他对象的引用仍然指向原来的对象。例如:
char ori[]=“hello”;
char *copy=ori;
这里copy的赋值操作就是浅拷贝;copy的值等于ori的值,并且copy所指向的对象与ori相同,但是copy与ori并不是完全相等,并没有完全复制ori。
char ori[]="hello";
char *copy=new char[];
copy=ori;
深拷贝是把要复制的对象所引用的对象都复制了一遍,也就是复制对象含有了被复制对象相同的值,但是引用的对象是被复制过的新对象,而不再是被复制对象所指的对象。