操作符重载

来源:互联网 发布:淘宝客户运营平台在哪 编辑:程序博客网 时间:2024/05/23 00:20

  • 一 前置与后置incrementdecrement
  • 二 不重载操作符
  • 三 关于new和delete
    • new operator和operator new
    • Placement new
    • 小节
    • 删除与内存释放
  • 总结

一 前置与后置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的完成任务方式。
原创粉丝点击