C++可执行程序的数据存储区域划分为 只读数据区、全局/静态存储区、自由存储区、栈区、堆区。
数据在内存中的位置包括两个部分:一是数据放置的位置,二是数据放置的格式。
只读数据区:存储于只读数据区的数据一般不允许修改,当然不可修改是相对的,通过一些非正常手段还是可以修改的。
全局/静态存储区 : 全局变量因为生存期相同,所以程序将其分配在同一片区域中。
自由存储区:自由存储区是CRT(c运行时库)通过malloc、free 函数管理的内存。在部分编译器实现上,与堆区是同一种管理方式。
栈区:栈区中的数据由编译器自动分配和释放。
堆区:指由new分配的内存块,编译器不负责它们的释放。 分配在堆区的内存的释放由应用程序自己去控制。如果程序员 没有释放掉,那么在程序结束后,由操作系统自动回收。
数据截断分析
int iValue=0x2345;
char cValue=(char)iValue;
最后cValue的值到底是多少呢? 这与CPU是大端还是小端有关系。
在C++构造函数中如果成员变量是CONST或引用类型,一定要初始化,而不能使用赋值操作。
C++有着固定的初始化顺序,基类先于子类初始化,class中的变量总是以变量声明的顺序进行初始化,和成员初始化列表顺序无关,因此在成员初始化列表中初始化各变量时,最好以声明次序为顺序。
几个问题:
1。单例模式
2。线程安全性
3。
Question:对象指针与对象的引用有何区别????
C++新特性(类与对象的各种指针和引用) - pearl333的专栏
http://blog.csdn.net/pearl333/article/details/8027358
《引用难道只是别人的替身》
引用类型是一个变量的别名,引用变量没有地址,甚至它们可能不占用任何存储空间。(难道是在编译阶段就被处理掉了)。
由于引用变量“没有地址”,所以下面一些事情不能干:
1。声明引用的引用,指向引用的指针,指向引用的数组都是非法的。
2。引用类型不能用关键字const修饰 volatile修饰,否则会引用编译错误。如果有时候编译器不提示错误,可能是这些错误被编译器忽略掉了。
3.函数使用指向数组的引用作为参数,可以保留数组的长度信息,而指针不会保留数组的长度信息。
void Array_test1(int (&array)[3]); //引用形式数组作为参数,不能用一个长度为2的数组作为其参数。
void Array_test1(int array[3]); //对数组长度不作限制。
常量引用(const reference )
int &rint=12; //错误
const int &rint=12; // 正常编译通过
可以看出常量值不能给普通引用初始化,但可以给const引用初始化。上面两行代码中引用rint指向编译器隐式分配内存并创建的匿名int类型临时对象。对rint引用的任何操作都会影响匿名临时变量,而不会影响常量12。同时编译器也会确保这样的匿名临时对象的生存期扩展到引用存在的全部时域。更近一步的了解,看下面这段代码。
short s=123;
const int& rIntegrate=s;
s=321;
const int *ip =&rIntegrate;
cout<<rIntegrate<<"\t"<<s<<endl;
cout<<ip<<"\t"<<&s<<endl;
输出结果:
可以看出rIntegrate引用的默认值并不是s,而是常量引用初始化过程中隐式使用的临时对象。
下面看一下const引用作为函数参数存在在的问题。
const int& GetMax(const int& a,const int& b){
return (a>b)?a : b;
}
请谨记:
- 若非必要请不要使用const引用,因为其伴随临时对象的产生。
- 在函数声明时,尽量避免使用const引用类型参数。
- 枚举类型
在c++中枚举类型中各成员的值可以不唯一,两个枚举成员可以具有相同的值。由于枚举类型的本意是提高程序可读性,避免使用magic number,所以在对枚举类型进行初始化时不能用int或其他整型值,即使该值与枚举类型相关联。
关于宏和枚举类型的比较:
1。枚举类型有类型检查,而宏没有类型检查。枚举类型 可以对参数进行合法性检查。而宏在遇到非法参数时可能不会有任何处理,需要通过相应语句进行判断。
2。宏没有作用域,宏定义后的代码都可以使用这个宏。
3。宏可以被重复定义。这可能导致宏的值被修改。
c++中定义二叉树结点时避免递归定义错误、相互包含引用错误。因为C++采用静态编译模型,在程序运行时,结构和类大小都需要在编译时确定。
在vs2010k ,错误C2460代表这种递归定义错误。
类或结构体递归定义的几个经典解决方法:
1。前向声明实现
Subject.h 头文件如下:
#ifndef SUBJECT_H
#define SUBJECT_H
#include <iostream>
#include "Observer.h"
class Observer;
class Subject
{
public:
void Info(){ std::cout <<" Subject !/n"; }
protected:
private:
Observer * myObserver;
};
#endif
Observer.h 头文件如下:
#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>
#include "Subject.h" //对于文件包含关系,要尽量避免循环引用。
class Subject;
class Observer
{
public:
void PrintInfo(){std::cout<<" In Observer !"<<std::endl;}
protected:
private:
Subject* mySubject;
};
事实上,只要打破类声明的递归链,就能解决类定义找不到的问题。
2。friend声明实现
//A.h 头文件
class CA{
public :
friend class CB; //将CB声明为CA的友元类。
CB* ptr_CB;
}
//B.H 头文件
#include “A.H”
class CB{
public :
CA instanceA;
}
class CA包含class CB 友元声明,而没有包含头文件B.h,这样只能声明CB类型的指针,而不能实例化。
上面两种方法中,有一点是肯定的,只有一个类中可以声明另一个类的实例,另一个中只能使用指针。