我的 c++的学习笔记(一)
1, char a[ ] = {'a', 'b', 'c'};
char b[ ] = {"abc"};
cout<<a<<endl;
cout<<strlen(a)<<endl;
cout<<b<<endl;
cout<<strlen(b)<<endl;
字符数组的两种初始化方式: 初始化列表(一定要以‘\0’结尾,否则结果意想不到),字符串字面值,编译器会自动添加‘\0’
2, const指针,指向const的指针,注意typedef之后的判断
Typedef string* pString;const pString cstr;
则cstr就是const指针,而不是指向const的指针,相当于,string* const cstr
typedef的一些用法(应该专题)
3,printf(“\r”);表示的是回车,但是没有换行
4,一些宏的妙用: __LINE__ ,__FILE__ ,__FUNCTION__, __FILEW__, __FUNCTIONW__
5,assert的妙用,(应该专题)assert(p == NULL&& “what”);可以同时显示一字符串。
6,const成员必须在初始化列表中进行初始化,因为它不能被赋值,同引用
7,const int *pci = new const int(1024);1024是pci所指空间的立即初始化!
当然如果是个类类型,不显式初始化会调用默认构造函数。
8,delete表达式只能用在被new动态分配的内存和空指针上(因为不会出现大错)
9,auto_ptr类的使用 include<memory> 解释所有权的问题,get(),release(),reset();
10,void *area = operator new (sizeof CImage);
CImage *ptr = new (area) CImage(“清明上河图”);
但是这时候就要手动调用ptr的析构函数,然后调用delete删除这块指针。
11,类可以应用显式初始化列表,但是这样类的数据成员必须是公有,而且容易出错。
1 操作符首先要确定它的返回值是左值,还是右值,如果是左值 返回引用,如果是右值那就直接返回值;
2 +号等这样的操作符没有对象可以容纳改变后的值,对于这样的情况最好返回数值,否则只能要操作符体内创建临时对象用于容纳改变后的值,如果在堆中创建临时对象返回指针或者引用,在操作符函数体外还需要释放它,如果返回的对象而不是引用或者指针,那么效率是比较低的。如果返回的是数值,最好在该类的构造函数中增加对该类型数值的转换函数,如:返回值是int类型,那么最好有一个int类型作为参数的构造函数。
3 前自增和后自增:
在增量运算符中,放上一个整数形参,就是后增量运行符,它是值返回,对于前增量没有形参,而且是引用返回,
Test &operator ++(); //前增量
Test &operator ++(int);//后增量
4除了对( )操作符外,对其他重载操作符提供缺省实参都是非法的;
13,自己重写operator new时,很重要的一点是函数提供的行为要和系统缺省的operator new一致。实际做起来也就是:要有正确的返回值;可用内存不够时要调用出错处理函数;处理好0字节内存请求的情况。此外,还要避免不小心隐藏了标准形式的new。
非类成员形式的operator new的伪代码:
void * operator new(size_t size) // operator new还可能有其它参数
{
if (size == 0) // 处理0字节请求时,
{
size = 1; // 把它当作1个字节请求来处理
}
while (1)
{
分配size字节内存;
if (分配成功)
return (指向内存的指针);
// 分配不成功,找出当前出错处理函数
new_handler globalhandler = set_new_handler(0); //
set_new_handler(globalhandler);
if (globalhandler) (*globalhandler)();
else throw std::bad_alloc();
}
}
为特定类写的new往往没有考虑该类被继承的情况,使用sizeof(父类)获得大小,但是如果发生子类调用父类的new时,往往
会出错,子类的size往往大于父类的size。最好父类的new应该这么写:
void * base::operator new(size_t size)
{
if (size != sizeof(base)) // 如果数量“错误”,让标准operator new,精华部分。
return ::operator new(size); // 去处理这个请求
//
... // 否则处理这个请求
}
对于operator delete(以及它的伙伴operator delete[]),情况更简单。所要记住的只是,c++保证删除空指针永远是安全的,所以你要充分地应用这一保证。
下面是非类成员形式的operator delete的伪代码:
void operator delete(void *rawmemory)
{
if (rawmemory == 0) return; //如果指针为空,返回
//
释放rawmemory指向的内存;
return;
}
这个函数的类成员版本也简单,只是还必须检查被删除的对象的大小。假设类的operator new将“错误”大小的分配请求转给::operator new,那么也必须将“错误”大小的删除请求转给::operator delete:
void base::operator delete(void *rawmemory, size_t size)
{
if (rawmemory == 0) return; // 检查空指针
if (size != sizeof(base)) // 如果size"错误",
{
::operator delete(rawmemory); // 让标准operator来处理请求
return;
}
释放指向rawmemory的内存;
return;
}
有关operator new和operator delete(以及他们的数组形式)的规定不是那么麻烦,重要的是必须遵守它。只要内存分配程序支持new-handler函数并正确地处理了零内存请求,就差不多了;如果内存释放程序又处理了空指针,那就没其他什么要做的了。至于在类成员版本的函数里增加继承支持,那将很快就可以完成。
作者:康斯特
个人WIKI(常年更新):http://dev.wannaplay.cn/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
期待技术交流,共同进步