符号重载让C++负重前行,丑陋不堪,如履薄冰

不得不说, 符号重载使C++实现了很多优秀的功能。

优点:

比如 智能指针,依赖对指针的赋值来计数,自动析构减少计数,防止指针内存泄露
比如 让代码更简洁,用一个简单的符号 如[], < , ==, () 帮助程序员完成了很多需要手写的函数。写java的一定深有体会

缺点:

把大量问题隐藏在重载的代码中。就好比一个总是溺爱女儿的老父亲,女儿不喜欢释放内存,那我就帮你保护起来。问题的本质是,不按规矩写代码,用再多的补救措施,那个不按规矩来的人依然是漏洞百出的。
再来说代码调试,重载符号的函数怎么跟进怎么看,是不是很麻烦。哪里的一个看是普通的一行代码,蕴含了大量重载符号函数的操作,不禁让程序员吓一跳,就这一行代码怎么发生这么多我不知道的事,还是老老实实写好函数名称,老老实实调用函数接口吧。

看看std boost 模板库里,让人眼花缭乱的源码,都不谈可读性和可理解性,这难道是我们对优秀的定义?不禁困惑,如果我们自己设计通用的模板库,也会把代码写成这样吗?
有幸对比了纯C语言的 list tree 等的纯宏实现,简洁明了可读性高,虽然可能编码习惯和安全性每个人不一样,但对比std容器简直好太多。

举一个例子:

std:set 默认有序,采用红黑树有序存储。可用 < 比较器 和 () 来实现唯一性。 隐含的规则如下

1. f(x,x) = false; 
2. if f(x,y) then !f(y,x)
3. if f(x,y) and f(y,z) then f(x,z)
4. if !f(x,y)&&!f(y,x) then x==y; if x==y and y==z then x==z;

set容器在判定已有元素a和新插入元素b是否相等时,如果采用 less比较器 bool operator() (const myclass& op),是这么做的:
1)将a作为左操作数,b作为有操作数,调用比较函数,并返回比较值
2)将b作为左操作数,a作为有操作数,再调用一次比较函数,并返回比较值。
如果1、2两步的返回值都是false,则认为a、b是相等的,则b不会被插入set容器中;
如果1、2两步的返回值都是true,则可能发生未知行为,
因此,记住一个准则:永远让比较函数对相同元素返回false。

如果有()重载 就使用这个比较傲规则,同样 永远让比较函数对相同元素返回false。

class vector_cmp{
public:
    bool operator()( const std::vector<int> v1,const std::vector<int> v2)
    {
        if (v1.size() != v2.size()) 
            return v1.size() < v2.size();
        if (v1.size() != 3) 
            return false;
        if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2]==v2[2])
            return false;
        if (v1[0] != v2[0])
            return v1[0] < v2[0];
        if(v1[1] != v2[1])
            return v1[1] < v2[1];
        if (v1[2] != v2[2])
            return v1[2] < v2[2];
        return false;
    }
};
void insert_set(std::set<std::vector<int>, vector_cmp>& myset)
{
    std::vector<int> v1 = {1, 2, 3};
    std::vector<int> v2 = {1, 2, 4};
    std::vector<int> v3 = {1, 2, 3};
    std::vector<int> v4 = {3, 4, 8};

    myset.insert(v1);
    myset.insert(v2);
    myset.insert(v3);
    myset.insert(v4);
}

上面这个 set 希望存储不重复的三元组,假设三元组是已经排序好的。 那么问题是, 插入 v1、v2、v3、v4的时候,重载函数()分别运行几次。
答案是0,3,3,4

in operator ()(1,2 , 4)===(1,2 , 3)
in operator ()(1,2 , 3)===(1,2 , 4)
in operator ()(1,2 , 4)===(1,2 , 3)
in operator ()(1,2 , 3)===(1,2 , 3)
in operator ()(1,2 , 3)===(1,2 , 4)
in operator ()(1,2 , 3)===(1,2 , 3)
in operator ()(3,4 , 8)===(1,2 , 3)
in operator ()(3,4 , 8)===(1,2 , 4)
in operator ()(1,2 , 4)===(3,4 , 8)
in operator ()(3,4 , 8)===(1,2 , 4)

总结:

回首细看标准库的源码,再对比现有的优秀的开源C++框架,很明显的问题是开源的普遍在符号重载上有意退避。回想起十年前,搞编译器、系统编译优化的老教授,语重心长的在课堂上大肆批评符号重载,我们还在疑惑是不是他老了接收不了新事物,现在我不怀疑。
凡事有利必有蔽,双刃剑还得利用优良特性,同时避其糟粕。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • C++运算符重载-上篇 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符和二元逻辑运算符4...
    Haley_2013阅读 2,291评论 0 51
  • 简书终于更新了代码高亮功能, 似乎呼唤着我回归, 那么就来一发良心之作时隔一年, 重读C++ Primer这本圣经...
    Andrew_liu阅读 2,528评论 2 26
  • 本教程旨在提取最精炼、实用的C++知识点,供读者快速学习及本人查阅复习所用,后期会持续更新。 基本语法 C++ 语...
    丁俊杰_阅读 5,887评论 0 8
  • Hi!这里是山幺幺的c++ primer系列。写这个系列的初衷是,虽然在学校学习了c++,但总觉得对这门语言了解不...
    山幺幺阅读 592评论 0 0
  • C++语言的八股文 C++面向对象的特性 封装——隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互,将数据和...
    wolfaherd阅读 816评论 1 3