C++【侯捷】——— const和new
const
const只能放在成员函数的后面,不能放在全局函数的后面。
const object(data不可以改变) | non-const object(data可以改) | |
---|---|---|
const member functions(函数保证不改数据) | 可以 | 可以 |
non-const member functions(函数可能改数据) | 不可以 | 可以 |
错误使用:常量对象调用非常量函数。non-const member function
const String str(“hello world”);
str.print();
函数重载中,后面加const可以算是重载的一种。
COW:copy on write。有共享的使用,常量字符串即使有要修改的内容就不用考虑OCW,所以一般有两种重载,就是函数后面加const,常量对象调用常量成员方法。
当一个对象的成员函数的const和non-const版本同时存在,const object指挥/只能调用const版本,non-const object只会/只能调用non-const版本。
new和delete
new和delete都是表达式,里面调用的是operator new和operator delete。表达式的形式是不能重载的,但是其分解下去的操作符是可以重载的。
new先分配memory,再调用构造函数。
delete先调用析构函数,再释放memory。
自己的class可以重载这些函数,用来做内存的分配和管理。
当自己有重载的时候hi调用到重载里面,如果没有就会调用全局的new和delete函数。下面是重载全绝的new和delete
void* myAlloc(size_t size) { ... }
void myFree(void* ptr) { ... }
inline void* operator new(size_t size)
inline void* operator new[](size_t size)
inline void operator delete(void* ptr)
inline void operator delete[](void* ptr)
也可以对成员函数的new和delete进行重载。
class Foo {
public:
void* operator new(size_t);
void* operator new[](size_t);
void operator delete(void* , size_t); //第二个参数可以不要
void operator delete[](void* , size_t); //第二个参数可以不要
}
如果使用者要绕过自定义的new和delete,可以这样写:
Foo* pf=::new Foo;
::delete pf;
带中括号的是创建和删除数组的对象,使用数组进行分配的时候空间会多一个字节,用来存放counter。除了可以重载上面的单一和数组形式的new和delete,也可以重载带小括号的new和delete,可以重载不同版本的new和delete,每一个版本必须有不同的参数序列,而且每一个的第一个参数必须是size_t。
delete也可以重载对应多个版本,但是他们绝不会被delete调用。这里说的delete是全绝delete中调用delete方法。只有当new所调用的构造函数抛出异常,才会调用这些版本的delete。不和new对应一一写出delete,也不会报错,不是强制的。
basc_string例子
class basic_string
{
private:
struct Rep {
...
inline static void* operator new(size_t size_t);
inline static void operator delete(void *);
inline static Rep* create(size_t);
...
};
...
};
basic_string <charT, traits, Allocator> ::Rep::create(size_t extra)
{
...
Rep *p=new(extra) Rep;
...
};
new会调用到里面的operator new,就相当于无声无息的多分配了空间。