操作符重载

一 前置与后置increment/decrement

  • 含义与形式
    参照C++的int ++操作符,重载可有两种含义:1.increment -> fetch. 2. fetch -> increment。
    重载operator++通过参数int来区分后置还是前置。
class Int{
public:
    const Int operator++(int);  //后置++
    Int & operator++();  //前置++
    Int & operator+=(int);
};
  • 实现
Int& Int::operator++(){
    *this += 1;  //使用operator+=
    return *this;
}
const Int Int::operator++(int/*不添加形参防止编译器警告*/){
    Int old_value = *this;
    ++(*this);  //由本身前置实现
    return old_value;
}
  • 要点
    1. 后置operator++返回const对象,保持与内置类型含义相同,不允许i++++的形式存在,因为后置operator++返回的是临时对象。
    2. 后置operaotr++以前置operator++作为基础,以便维护。
    3. 后置operator++产生了临时对象构造、析构,效率低,优选前置operator++。

二 不重载&&、||、,操作符

  • 求值顺序
    &&、||采用“短路”求值,逗号操作符operator ,具有顺序求值特性。可见三者天生对于操作数是有求值顺序的。
  • 重载&&、||、,
    重载后,三者对于求值顺序不可控,偏离了原来的含义。容易使用出错。
//重载&&,不能控制参数评估顺序
if (exp1 && exp2) ...
//可能是以下两种形式
if (exp1.operator&&(exp2)) ... //成员
if (operator&&(exp1, exp2)) ... //全局
  • 目的
    操作符重载的目的在于让程序容易被阅读、被撰写、被理解

三 关于new和delete

new operator和operator new

当写出以下代码便是使用到了语言内建的new operator。

string *ps = new string("hello world");

new operator的行为是固定的,不可改变的,它的动作分为两方面
1. 为了放置某个对象分配足够的内存空间。
2. 在该内存空间上调用对象的构造函数,设定初始值。
其中针对1条款,我们是可以定制的,也就是更改原始内存分配的行为,即重载operaotor new,通常声明如下,返回值为原始未初始化的内存。

void* operator new(size_t size);

类似于于malloc,operator new的唯一任务就是分配内存。它并不知道什么是构造函数以及如何将内存转换为对象。可直接调用它分配内存如下。

void *raw_memory = operator new (sizeof(string));

对于代码

string *ps = new string("hello world");

或多或少反应如下行为

void *memory = operator new(sizeof(string)); //取得原始内存
call string::string("hello world") on memory; //内存对象初始化
string *ps = static_cast<string*>(memory); //ps指向对象

Placement new

以上说明的new operator将内存分配、对象构建一气呵成。但有时候我们希望在自己已有内存空间上来构建对象。此时有一个特殊版本的operator new称为placement new允许那样做。

class C{
public:
    C();
    ...
};
C* ConstructCInBuffer(void* buf, int size){
    return new(buf) C(size);
}

其中 new(buf) C(size)正是placement new的用法。buf为用户提供的用来接受构造好的对象的空间。Placement new的实现看起来如下:

void *operator new(size_t, void *location){
    return location;
}

由于operator new的作用是分配原始内存,既然用户已经提供了内存空间,所以只是简单的返回该空间。

小节

  1. 如果希望对象产生于heap,调用new operator
  2. 如果只是打算分配内存,则使用operator new
  3. 如果使用new operator时希望自己控制内存的分配方式,则重写或重载operator new
  4. 如果希望在自己已经准备好了内存空间产生对象时,则只需使用placement new即可

删除与内存释放

针对资源分配必须有匹配的资源释放。
当写出以下代码

std::string *str;
...
delete str;

代码必须做两件事:1. 析构str所指对象 2.释放该对象占用的内存。delete str会导致编译器产生如下代码:

str->~string();
operator delete(str);

operator delete对于delete operator来说就如operator new对new operator。这里一个暗示是如果只是涉及原始的、未初始化的内存那么用operator new来分配、用operator delete来销毁。类似c语言中的malloc和free。

void *buffer = operator new (50*sizeof(char));
...
operator delete(buffer);

总结

  • new operator和delete operator都是内建操作符,不能改变其任务。
  • operator new和operator delete可以被定制,改变new operator和delete operator的完成任务方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值