C++类型sizeof的值
- 空类型实例声明时需要占一定内存,一般为1byte
仅包含一个占位符
- 只拥有函数不拥有成员,类实例也为1byte
函数地址与类型有关,和类型的实例无关
- 拥有虚函数,类实例为4byte或者8byte,取决于机器的体系结构是32bit还是64bit
virtual为类型生成虚函数表,每个实例中都有一个指向虚函数表的指针
//1
class A{
};
//1
class B{
B(){}
~B(){}
};
//8
class C{
C(){}
virtual ~C(){}
};
//4
class D{
D(){}
~D(){}
int d;
};
//16
class E{
E(){}
virtual ~E(){}
int e;
};
void sizeTest(){
cout << "A "<< "B "<< "C "<<"D "<<"E "<<endl;
cout << sizeof(A) << " " << sizeof(B) << " " <<
sizeof(C) << " " <<sizeof(D) << " "<<sizeof(E)<<endl;
}
测试一下
A B C D E
1 1 8 4 16
C++的复制构造函数不能传值
- 类型A的复制构造函数若按值传入A的实例,则会在复制构造函数中调用复制构造函数,形成无休止的递归调用,最后栈溢出。
- 索性编译器会阻止这一尝试。
class E{
E(){}
E(E ee){e = ee.e;} //not ok
//E(const E &&ee){e = ee.e;} //ok
~E(){}
long e;
};
编译失败,
cpp:247:9: error: copy constructor must pass its first argument by
reference
E(E ee){e = ee.e;}
^
const &
C++的异常安全性
考虑写一个字符串封装类型的复制构造操作符。
class CMString{
public:
CMString(char * pd = NULL):m_pd(NULL){
if(pd == NULL) return;
m_pd = new char[strlen(pd)+1];
strcpy(m_pd, pd);
}
CMString(const CMString &s) = delete;
CMString & operator=(const CMString &s){
/* no exception-safe solution */
//check if src and dst are of the same instance
if(this == &s) return *this; //return reference to instance
//release original memory
delete []m_pd; //take care !!
m_pd = NULL;
m_pd = new char[strlen(s.m_pd)+1];
strcpy(m_pd, s.m_pd);
return *this;
}
~CMString(){
if(m_pd)
delete []m_pd;
}
char * get() {
return m_pd;
}
private:
char * m_pd;
};
void strTest(){
CMString s1((char *)"string");
CMString s2((char *)"str");
s2 = s1;
cout << s2.get() << endl;
}
测试一下,
string
测试结果虽然是对的,但是在分配内存之前先释放了m_pd的内存,如果分配失败,异常抛出,实例不再有效,这违背了异常安全性的原则。
可以修改一下,用一个临时的中间实例来中转数据,旧数据通过中间实例来释放。这样可以在内存分配失败时确保原来的数据不会被修改。
CMString & operator=(const CMString &s){
if(this != &s){
CMString tmp(s.m_pd);
//exchange internal data and release the old data
// through tmp executing deconstructor
char *pTmp = tmp.m_pd;
tmp.m_pd = m_pd;
m_pd = pTmp;
}
return *this;
}
测试一下,结果同样是正确的。
C/C++没有记录数组的大小
C中,数组和指针的概念是关联而又存在区别的,数组的名字也是一个指针,指向第一个元素。但是C没有记录数组的大小。
int GetSize(int data[]){
return sizeof(data);
}
void sizeTest(){
int data1[] = {1, 2, 3, 4, 5};
int *data2 = data1;
cout << sizeof(data1) << " "<<GetSize(data1)<<" "<<sizeof(data2)<<endl;
}
测试一下,sizeof(data1)是求数组的大小4*5=20,传入函数后按指针处理,64bit上指针为8字节长。
20 8 8