吐槽C++

个人感觉,在c++ 道路的学习路上,遇到很多的坎坷,现在回想起来,最关键一点就是 c++知识点繁杂很多,教科书很多知识点都没有提到. 但是在实际工作中,这些没有提到的知识点,却又经常会用到(或者看开源代码里面有)。导致很多的代码看不懂,给弱小的内心受到不小的打击。一本大而全的C++书籍,虽难部分知识点当时可能看不懂,但是如果工作遇到后会再过去查得,但是书籍中不能因为隐蔽就不提。给学生一些恐慌.

比如:复制构造函数 与 赋值函数 的区别     ------如果教科书能提到这些感念,就不会对这块知识点纠结这么久了,其实也没什么难的,为什么不讲呢?  呵呵

构造函数、析构函数、赋值函数是每个类最基本的的函数。每个类只有一个析构函数和一个赋值函数。但是有很多构造函数(一个为复制构造函数,其他为普通构造函数。对于一个类A,如果不编写上述四个函数,c++编译器将自动为A产生四个默认的函数,即:

  • A(void)                                    //默认无参数构造函数
  • A(const A &a)                         //默认复制构造函数
  • ~A(void);                                //默认的析构函数
  • A & operator = (const A &a); //默认的赋值函数

既然能自动生成函数,为什么还需要自定义?原因之一是“默认的复制构造函数”和"默认的赋值函数“均采用”位拷贝“而非”值拷贝“

位拷贝  v.s.  值拷贝

为便于说明,以自定义String类为例,先定义类,而不去实现。

#include <iostream>
using namespace std;

class String
{
    public:
        String(void);
        String(const String &other);
        ~String(void);
        String & operator =(const String &other);
    private:

        char *m_data;
        int val;
};

  

位拷贝拷贝的是地址,而值拷贝拷贝的是内容。

如果定义两个String对象a, b。当利用位拷贝时,a=b,其中的a.val=b.val;但是a.m_data=b.m_data就错了:a.m_data和b.m_data指向同一个区域。这样出现问题:

  • a.m_data原来的内存区域未释放,造成内存泄露
  • a.m_data和b.m_data指向同一块区域,任何一方改变,会影响到另一方
  • 当对象释放时,b.m_data会释放掉两次

因此

当类中还有指针变量时,复制构造函数和赋值函数就隐含了错误。此时需要自己定义。

结论

  • 有一种特别常见的情况需要自己定义复制控制函数:类具有指针哈函数。
  • 赋值操作符和复制构造函数可以看成一个单元,当需要其中一个时,我们几乎也肯定需要另一个
  • 三法则:如果类需要析构函数,则它也需要赋值操作符和复制构造函数

注意

  • 如果没定义复制构造函数(别的不管),编译器会自动生成默认复制构造函数
  • 如果定义了其他构造函数(包括复制构造函数),编译器绝不会生成默认构造函数
  • 即使自己写了析构函数,编译器也会自动生成默认析构函数

因此此时如果写String s是错误的,因为定义了其他构造函数,就不会自动生成无参默认构造函数。

复制构造函数  v.s.  赋值函数

#include <iostream>
#include <cstring>
using namespace std;

class String
{
    public:
        String(const char *str);
        String(const String &other);
        String & operator=(const String &other);
        ~String(void);
    private:
        char *m_data;
};

String::String(const char *str)
{
    cout << "自定义构造函数" << endl;
    if (str == NULL)
    {
        m_data = new char[1];
        *m_data = ‘\0‘;
    }
    else
    {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

String::String(const String &other)
{
    cout << "自定义拷贝构造函数" << endl;
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
}

String & String::operator=(const String &other)
{
    cout << "自定义赋值函数" << endl; 

    if (this == &other)
    {
        return *this;
    }
    else
    {
        delete [] m_data;
        int length = strlen(other.m_data);
        m_data = new char[length + 1];
        strcpy(m_data, other.m_data);
        return *this;
    }
}

String::~String(void)
{
    cout << "自定义析构函数" << endl;
    delete [] m_data;
}
int main()
{
    cout << "a(\"abc\")" << endl;
    String a("abc");

    cout << "b(\"cde\")" << endl;
    String b("cde");

    cout << " d = a" << endl;
    String d = a;

    cout << "c(b)" << endl;
    String c(b);

    cout << "c = a" << endl;
    c = a;

    cout << endl;
}

  

执行结果

说明几点

1. 赋值函数中,上来比较 this == &other 是很必要的,因为防止自复制,这是很危险的,因为下面有delete []m_data,如果提前把m_data给释放了,指针已成野指针,再赋值就错了

2. 赋值函数中,接着要释放掉m_data,否则就没机会了(下边又有新指向了)

3. 拷贝构造函数是对象被创建时调用,赋值函数只能被已经存在了的对象调用

注意:String a("hello"); String b("world");  调用自定义构造函数

String c=a;调用拷贝构造函数,因为c一开始不存在,最好写成String c(a);

参考: http://www.cnblogs.com/kaituorensheng/p/3245522.html

吐槽C++,布布扣,bubuko.com

时间: 2024-10-09 04:20:42

吐槽C++的相关文章

还在吐槽翻译的外版书质量差吗?谈谈我个人的理解

很难想象哪个学习计算机技术的人是没看过这方面书籍的,如果只是在网上看看技术贴,那样得来的知识绝对是离散的,不系统的.而要真正学好一门学问(比如一门计算机语言或者一门技术),一本好书的作用是不言而喻的.很多人抱怨国人在技术图书方面抄来抄去,不求甚解,虽然出版图书者甚众,但最终成为精品者却凤毛麟角.于是,更多读者热衷于外版书.但显然,并非所有国人的外语水平都足以在阅读原版书籍时毫无障碍.那么退而求其次,寻求翻译版就成为一种看似不得已的选择. 不幸的是,网上对于翻译版书籍的吐槽可以说从未消停.我也看过

2017/8/4 考试吐槽

2017 8 4 得分:110 一句话:江南皮革厂倒闭了!会的东西全带着他们的小姨子跑了!成绩统统二十分!统统二十分! A.聪明的质检员 链接:http://cogs.pro/cogs/problem/problem.php?pid=631 题意:找到一个式子:Y_i = \sum_j 1 \times \sum_j v_j ,  j \in [L_i, R_i] \text{且} w_j \ge W, j \text{是矿石编号}与标准差绝对值最小的情况. 吐槽:二分写成三分--少写一个库--

吐槽。学习遇到的问题--虚拟机无法识别usb

我真的忍不住想吐槽一下,之前下载的VMware10然后识别不了USB 去度娘上搜半天,各种方法参差不齐 安装的不对,USB驱动没做好,版本太低.巴拉巴拉... 最多的就是,虚拟机设置中,USB设备没有连接,可是姐姐连了啊... 小白的我,虚拟机安了千百遍,驱动重装千百遍,从VM的网卡到virtal box乱七八糟..一直没搞好 我都开始对自己失望了,做个简单实验,在我这儿就跟西天取经了... 终于一个月的时间,我发现了问题所在..希望其他小白不要在瞎折腾了,其实真的很简单 首先, 按Win+R打

关于OpenCart的吐槽。。。

近段时间,由于产生了做网店的想法,作为一个粗浅的程序爱好者,就想着自己下载一个开源的电商系统.由于没有经验,在网上查了许多资料后,觉得OpenCart还不错,所以就开始摆弄起来. Opencart的优点是便于安装,速度比较快,目录结构清晰,采用MVC+L的架构方式,所以看他的源代码很方便,清晰易懂,功能也比较强大.一般下,我们只需要自己开发一个前台模板,这样我们的网站就可以上线了.我下载的是目前最新的2.3.0.2这个版本,与之前的版本有很大不同,开发一个主题的步骤,网上相应的资料也很少.经过自

xxx述职报告 某优秀新锐奖评选员工吐槽

那些背锅人员未曾给领导吐槽的话? ------做了一个调查,找出了几十年以来的创业风云人物,发现除了IT互联网领域之外,72个传统产业创业代表只有一个80后,其他都是老人了,还在把控传统帝国,即使是48个IT互联网创业大佬里,也只有九个80后,还只能捞偏门,主流被60后和70后控制了,真正的爆发性创业机会忽略不计,所谓万众创业,其实是骗局. 正文: xxx述职报告 一.个人情况简介(包括,姓名,部门,职位,负责的工作模块等) 姓名:XXX 部门:运营部 职位:linux运维工程师 工作模块:已踩

情人节吐槽一下刚起步的公众号运营

昨天,在老家飞上海的旅途中,刷到了这张图,简直百感交集,内牛满面: 然而日子还是要过的,文章还是要写的,单身狗也只能在2月14号这个日子写个杂文,还能把这张图用到极处. 在今年年初的时候,给自己订了个三个目标:计算机基础,英语,运营微信公众号.现在情人节灾难片已经全国上映了,这三个目标都还没有完全开始. 为了证明我还在努力执行目标,这里讲一下微信公众号的进度吧. 在年初决定要做公众号时,给自己简单写了一下做这个运营要做的事情 1个多月过去啦,现在公众号名字定啦:学会用PS分分钟搞定900*500

实力非吐槽

这个月6号,本打算写文章吐槽最近发生的一些事.当时真的是满腔愤怒,因为我从未遇到过如此奇葩的一个人,遭遇如此不堪的经历. 直到今天,事情总算告一段落,心中怒火也没当日那么多,但总想把这些事写下来,不知接下来会是吐槽呢,还是静静的思考呢? 6号正值周日,本该是休息的时间,然而我却被叫了过去,修改程序中的问题,周折一番竟发现问题根本不出在我这.之前也有类似的加班情形,不说了. 那么问题来了,上个星期,我为什么会额外加班那么多时间? 最近遇到一个特别特别“厉害”的项目交接人,且称他为C吧.C每次需要新

有关html5设计那些事,你真的考虑过前端的实现吗(最近别人经常问我这种问题,所以我就写一篇了,可能也有别人和我一样吐槽过)

很久以前在安卓2.0系统刚刚的时候就对HTML5比较关注!因为我也是那个时候刚刚入行做前端的.那个时候最大的乐趣就是看着w3plus上面各种css3的效果,觉得哇,好牛逼原来可以这样做,然后3年过去了...手上的APP做完的没有40个也有30个了!然后去年参加了HTML5峰会.听着一批前辈们说着他们在html5的道路中遇到的挫折,经验,以及流行的框架,制作HTML5的ide...也算是小有经验了!...然后知道的越多,现实就越残酷(大漠竟然说他不会JS,无语偶曾经的偶像竟然说他真的不会js还发誓

吐槽网上冲印

互联网这么发达,作为宅男能不出门的坚决网上解决(可以理解这是强迫症). 偶尔想冲印些照片,发现网上冲印的网站还挺多,发现当初应该学个PS的,照片太"自然"了. 纯粹的冲洗照片没啥意思,干脆冲洗相册,不差这几个钱. 像印象派.咔嚓鱼这些网站都有在线相册制作软件,还可以处理照片,现在的服务做得还是挺到位的. 不过,相册款式不多,女友不喜欢,只能发挥下平时向她吹嘘擅长使用的搜索引擎了,最终搜到叫贝壳图的,http://shop.becktu.com,难得找到一款让一向挑剔的女友满意的相册,h

吐槽Windows 8,就没见过这么烂的平板操作系统

本文带有严重个人情感色彩,反感者慎入. CSDN 博文大赛得了个奖品,联想的平板电脑, MIIX2 8 ,系统是 Windows 8 . 今天媳妇再次使用它,惹得我再次吐槽. 一句话,Windows 8 这系统设计得,简直不是给人用的,它是真心给你找麻烦的. 举几个例子吧. 关于账号 作为一个平板电脑,为毛非要我设置一个帐号?我是电脑用户吗?我需要吗?你真觉得我需要吗?你为什么要强奸我呢? 我是有可能需要一个账号,可为什么不能默认不用帐号就可以使用,让有需要的人到"高级"设置中去为安全