iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >c++编程的技巧
  • 265
分享到

c++编程的技巧

2023-06-15 10:06:30 265人浏览 安东尼
摘要

这篇文章主要介绍c++编程的技巧,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、以良好的方式编写C++ class假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯。Header(头文件

这篇文章主要介绍c++编程的技巧,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1、以良好的方式编写C++ class

假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯。

Header(头文件)中的防卫式声明

complex.h:

# ifndef  __COMPLEX__# define __COMPLEX__class complex{    }# endif

防止头文件的内容被多次包含。

把数据放在private声明下,提供接口访问数据

# ifndef  __COMPLEX__# define __COMPLEX__class complex{    public:        double real() const {return re;}        double imag() const {return im;}    private:        doubel re,im;}# endif

不会改变类属性(数据成员)的成员函数,全部加上const声明

例如上面的成员函数:

double real () `const` {return re;}double imag() `const` {return im;}

既然函数不会改变对象,那么就如实说明,编译器能帮你确保函数的const属性,阅读代码的人也明确你的意图。
而且,const对象才可以调用这些函数——const对象不能够调用非const成员函数。

使用构造函数初始值列表

class complex{    public:        complex(double r = 0, double i =0)            : re(r), im(i)  { }    private:        doubel re,im;}

在初始值列表中,才是初始化。在构造函数体内的,叫做赋值。

参数尽量使用reference to const

为complex 类添加一个+=操作符:

class complex{    public:        complex& operator += (const complex &)}

使用引用避免类对象构造与析构的开销,使用const确保参数不会被改变。内置类型的值传递与引用传递效率没有多大差别,甚至值传递效率会更高。例如,传递char类型时,值传递只需传递一个字节;引用实际上是指针实现,需要四个字节(32位机)的传递开销。但是为了一致,不妨统一使用引用。

函数返回值也尽量使用引用

以引用方式返回函数局部变量会引发程序未定义行为,离开函数作用域局部变量被销毁,引用该变量没有意义。但是我要说的是,如果可以,函数应该返回引用。当然,要返回的变量要有一定限制:该变量的在进入函数前,已经被分配了内存。以此条件来考量,很容易决定是否要返回引用。而在函数被调用时才创建出来的对象,一定不能返回引用。

说回operator +=,其返回值就是引用,原因在于,执行a+=b时,a已经在内存上存在了。

而operator +,其返回值不能是引用,因为a+b的值,在调用operator +的时候才产生。

下面是operator+=与'operator +' 的实现:

inline complex & complex :: operator += (const complex & r){    this -> re+= r->re;    this -> im+= r->im;    return * this;}inline complex operator + (const complex & x , const complex & y){    return complex ( real (x)+ real (y), //新创建的对象,不能返回引用    imag(x)+ imag(y));}

在operator +=中返回引用还是必要的,这样可以使用连续的操作:

c3 += c2 += c1;

如果重载了操作符,就考虑是否需要多个重载

就我们的复数类来说,+可以有多种使用方式:

complex c1(2,1);complex c2;c2 = c1+ c2;c2 = c1 + 5;c2 = 7 + c1;

为了应付怎么多种加法,+需要有如下三种重载:

inline complex operator+ (const complex & x ,const complex & y){    return complex (real(x)+real(y),                    imag(x+imag(y););}inline complex operator + (const complex & x, double y){    return complex (real(x)+y,imag(x));inline complex operator + (double x,const complex &y){    return complex (x+real(y),imag(y));}

提供给外界使用的接口,放在类声明的最前面

这是某次面试中,面试官大哥告诉我的。想想确实是有道理,类的用户用起来也舒服,一眼就能看见接口。

2、Class with pointer member(s)

记得写Big Three

C++的类可以分为带指针数据成员与不带指针数据成员两类,complex就属于不带指针成员的类。而这里要说的字符串类String,一般的实现会带有一个char *指针。带指针数据成员的类,需要自己实现class三大件:拷贝构造函数、拷贝赋值函数、析构函数。

class String{    public:        String (const char * cstr = 0);        String (const String & str);        String & operator = (const String & str);        ~String();        char * get_c_str() const {return m_data};    private:        char * m_data;}

如果没有写拷贝构造函数、赋值构造函数、析构函数,编译器默认会给我们写一套。然而带指针的类不能依赖编译器的默认实现——这涉及到资源的释放、深拷贝与浅拷贝的问题。在实现String类的过程中我们来阐述这些问题。

析构函数释放动态分配的内存资源

如果class里有指针,多半是需要进行内存动态分配(例如String),析构函数必须负责在对象生命结束时释放掉动态申请来的内存,否则就造成了内存泄露。局部对象在离开函数作用域时,对象析构函数被自动调用,而使用new动态分配的对象,也需要显式的使用delete来删除对象。而delete实际上会调用对象的析构函数,我们必须在析构函数中完成释放指针m_data所申请的内存。下面是一个构造函数,体现了m_data的动态内存申请:

inline String ::String (const char *cstr = 0){    if(cstr)    {        m_data = new char[strlen(cstr)+1];   // 这里,m_data申请了内存        strcpy(m_data,cstr);    }    else    {        m_data= new char[1];        *m_data = '\0';    }}

这个构造函数以C风格字符串为参数,当执行

String *p = new String ("hello");

m_data向系统申请了一块内存存放字符串hello:

c++编程的技巧

析构函数必须负责把这段动态申请来的内存释放掉:

inline String ::~String(){    delete[]m_data;}

赋值构造函数与复制构造函数负责进行深拷贝

来看看如果使用编译器为String默认生成的拷贝构造函数与赋值操作符会发生什么事情。默认的复制构造函数或赋值操作符所做的事情是对类的内存进行按位的拷贝,也称为浅拷贝,它们只是把对象内存上的每一个bit复制到另一个对象上去,在String中就只是复制了指针,而不复制指针所指内容。现在有两个String对象:

String a("Hello");String b("World");

a、b在内存上如图所示:

c++编程的技巧

如果此时执行

 b = a;

浅拷贝体现为:

c++编程的技巧

存储World\0的内存块没有指针所指向,已经成了一块无法利用内存,从而发生了内存泄露。不止如此,如果此时对象a被删除,使用我们上面所写的析构函数,存储Hello\0的内存块就被释放调用,此时b.m_data成了一个野指针。来看看我们自己实现的构造函数是如何解决这个问题的,它复制的是指针所指的内存内容,这称为深拷贝

inline String &String ::operator= (const String & str){    if(this == &str)           //①        return *this;    delete[] m_data;        //②    m_data = new char[strlen(str.m_data)+1];        //③    strcpy(m_data,str.m_data);            //④    return *this}

这是拷贝赋值函数的经典实现,要点在于:

① 处理自我赋值,如果不存在自我赋值问题,继续下列步骤:

② 释放自身已经申请的内存

③ 申请一块大小与目标字符串一样大的内存

④ 进行字符串的拷贝

对于a = b,②③④过程如下:

c++编程的技巧

c++编程的技巧

c++编程的技巧

同样的,复制构造函数也是一个深拷贝的过程:

inline String ::String(const String & str ){    m_data = new char[ strlen (str) +1];    strcpy(m_data,str.m_data);}

另外,一定要在operator = 中检查是否self assignment假设这时候确实执行了对象的自我赋值,左右pointers指向同一个内存块,前面的步骤②delete掉该内存块造成下面的结果。当企图对rhs的内存进行访问是,结果是未定义的。

c++编程的技巧

3、static与类

不和对象直接相关的数据,声明为static

想象有一个银行账户的类,每个人都可以开银行账户。存在银行利率这个成员变量,它不应该属于对象,而应该属于银行这个类,由所有的用户来共享。static修饰成员变量时,该成员变量放在程序的全局区中,整个程序运行过程中只有该成员变量的一份副本。而普通的成员变量存在每个对象的内存中,若把银行利率放在每个对象中,是浪费了内存。

static成员函数没有this指针

static成员函数与普通函数一样,都是只有一份函数的副本,存储在进程的代码段上。不一样的是,static成员函数没有this指针,所以它不能够调用普通的成员变量,只能调用static成员变量。普通成员函数的调用需要通过对象来调用,编译器会把对象取地址,作为this指针的实参传递给成员函数:

obj.func() ---> Class :: fun(&obj);

而static成员函数即可以通过对象来调用,也可以通过类名称来调用。

在类的外部定义static成员变量

另一个问题是static成员变量的定义。static成员变量必须在类外部进行定义:

class A{    private:        static int a; //①}int A::a = 10;  //②

注意①是声明,②才是定义,定义为变量分配了内存。

static与类的一些小应用

这些可以用来应付一下面试,在实现单例模式的时候,static成员函数与static成员变量得到了使用,下面是一种称为”饿汉式“的单例模式的实现:

class A{        public:            static A& getInstance();            setup(){...};        private:            A();            A(const A & rhs);            static A a;}

这里把class A的构造函数都设置为私有,不允许用户代码创建对象。要获取对象实例需要通过接口getInstance。”饿汉式“缺点在于无论有没有代码需要a,a都被创建出来。下面是改进的单例模式,称为”懒汉式“:

class A{    public:         static  A& getInstance();        setup(){....};    private:        A();        A(const A& rsh);        ...};A& A::getInstance(){        static A a;        return a;}

"懒汉式"只有在真正需要a时,调用getInstance才创建出唯一实例。这可以看成一个具有拖延症的单例模式,不到最后关头不干活。很多设计都体现了这种拖延的思想,比如string的写时复制,真正需要的时候才分配内存给string对象管理的字符串。

以上是“c++编程的技巧”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网其他教程频道!

--结束END--

本文标题: c++编程的技巧

本文链接: https://www.lsjlt.com/news/279690.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c++编程的技巧
    这篇文章主要介绍c++编程的技巧,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、以良好的方式编写C++ class假设现在我们要实现一个复数类complex,在类的实现过程中探索良好的编程习惯。Header(头文件...
    99+
    2023-06-15
  • C++的编程技巧有哪些
    这篇文章主要介绍“C++的编程技巧有哪些”,在日常操作中,相信很多人在C++的编程技巧有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++的编程技巧有哪些”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-17
  • C++编程技巧有哪些
    这篇文章主要讲解了“C++编程技巧有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++编程技巧有哪些”吧!1.调试标记适用预处理#define定义一个或多个调试标记,在代码中把调试部分...
    99+
    2023-06-17
  • C#的Excel编程技巧有哪些
    小编给大家分享一下C#的Excel编程技巧有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一.C#的Excel程序设计及运行环境(1).微软视窗2000 服务...
    99+
    2023-06-17
  • C++编程技巧举例分析
    本篇内容介绍了“C++编程技巧举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在C++中,Windows类中的Sort方法将成为Lis...
    99+
    2023-06-17
  • C++ 函数式编程的实践技巧
    c++++ 函数式编程技巧包括:使用不可变对象、纯函数、高阶函数、lambda 表达式和流 api。具体实践案例:使用不可变单词列表、纯函数计算单词出现的次数、高阶函数找到出现次数最多的...
    99+
    2024-04-18
    c++ 函数式编程
  • C++语言的各种编程技巧分析
    这篇文章主要介绍“C++语言的各种编程技巧分析”,在日常操作中,相信很多人在C++语言的各种编程技巧分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++语言的各种编程技巧分析”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-17
  • C++图形编程优化技巧解疑
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-15
  • python的30个编程技巧
     1、原地交换两个数字 1 x, y =10, 20 2 3 print(x, y) 4 5 y, x = x, y 6 7 print(x, y) 10 20 20 10 2、链状比较操作符 1 n = 10 2 3 pr...
    99+
    2023-01-30
    编程技巧 python
  • C语言中的编码小技巧
    目录C语言编码小技巧1. 退出程序2. 注释(相当于“删除”)一段代码3.  数据溢出问题4. 增加程序的可读性5. Oj 1062 避免读取无关 ...
    99+
    2023-02-06
    C语言编码 编码小技巧 C语言编码技巧
  • 提升编程能力的C语言技巧总结
    目录一、函数指针1.概念2.如何用函数指针调用函数3.函数指针作为某个函数的参数4.函数指针作为函数返回类型5.函数指针数组6.函数指针总结二、回调函数1.什么是回调函数2.为什么要...
    99+
    2022-12-08
    C语言 技巧
  • Python异常编程技巧
    编程中经常会需要使用到异常处理的情况,在阅读了一些资料后,整理了关于异常处理的一些小技巧记录如下。 如何自定义异常 定义异常类 在实际编程中,有时会发现Python提供的内建异常的不够用,我们需要在特殊业务场景下的异常。这时就需要我们来定...
    99+
    2023-01-31
    异常 编程技巧 Python
  • python编程技巧——转载
    学用python也有3个多月了,用得最多的还是各类爬虫脚本:写过抓代理本机验证的脚本,写过在discuz论坛中自动登录自动发贴的脚本,写过自动收邮件的脚本,写过简单的验证码识别的脚本,本来想写google music的抓取脚本的,结果有了强...
    99+
    2023-01-31
    编程技巧 python
  • C++图形编程并行计算技巧揭秘
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-16
  • 3个 Python 编程技巧
    目录1、如何按照字典的值的大小进行排序2、优雅的一次性判断多个条件3、如何优雅的合并两个字典今天分享 3 个 Python 编程小技巧,来看看你是否用过? 1、如何按照字典的...
    99+
    2024-04-02
  • Python的编程技巧有哪些
    以下是一些Python编程的技巧:1. 使用列表推导式:列表推导式是一种简洁的方式来创建列表。它可以通过迭代一个可迭代对象,并根据条...
    99+
    2023-09-25
    Python
  • Python编程开发技巧
    这篇文章给大家分享的是有关Python编程开发技巧的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、小数保留指定位小数1.%f 方法f = 1.23456f1 = '...
    99+
    2023-06-14
  • C++ 函数性能优化中的 MPI 并行编程技巧
    c++++ 函数性能优化中利用 mpi 并行编程时,可并行化不依赖于其它部分的代码段。具体步骤包括:创建 mpi 辅助进程并获取标识符;分散任务数据到各个进程;执行并行任务;收集并合并结...
    99+
    2024-04-23
    c++ mpi
  • Java编程技巧有哪些
    小编给大家分享一下Java编程技巧有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.使用HashSet判断主键是否存在HashSet实现Set接口,由哈希表...
    99+
    2023-06-05
  • web编程技巧有哪些
    本篇内容主要讲解“web编程技巧有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“web编程技巧有哪些”吧!您应该使用像map、filter和reduce这样...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作