C++编程中需要注意的几点

C++编程之自定义日志类 ——log4cpp使用详解 C++编程之自定义日志类 ——log4cpp使用详解log4cpp简介与安装log4cpp安装log4cpp简单介绍layout布局——日志输出格式log4cpp::BasicLayoutlog4cpp::PatternLayoutappenderlog4cpp::FileAppenderlog4cpp::RollingFileAppenderlog4cpp::OstreamAppenderlog... 阅读详情

1、最好不要使用引用返回值

有同学在传递的参数的时候使用引用方式传递,避免了临时对象的创建,提高了效率,那么在返回值的时候能不能使用引用呢?

看如下代码


        class Rational{
        public:
            Raional( int numerator = 0, int denominator =1);
            ...
        private:
            int d, d;
            friend Rational operator* (const Rational& lhs, const Raional& rhs) ;
        };
       Rational Rational::operator* (const Rational& lhs,const Raionl&rhs)
        {
                return Rational  result(lhs.n*rhs.n,lhs.d*rhs.d);
        } 
    }
  这个类就是我们前面所介绍的有理数类。这里想想会发生一次类的构造与类的析构,那么如果使用引用就可以避免这个问题吗?达到提高效率吗?

  函数创建新对象有两种方法,一个是在栈(statck)中创建,一个是在堆(heep)中创建。

        People p(a,b)                  //栈中创建
        People *p = new People(a,b)   //堆中创建
 现在首先考虑在栈中创建,但是这个创建的变量是一个局部变量,会在退出函数之前销毁。

   const Rational& operator* (const Rational& lhs, const Rational & rhs)
        {
            Rational  result(lhs.n*rhs.n,lhs.d*rhs.d);
            return result;
        }
  在函数内以stack方式空间创建对象是局部对象,任何函数如果返回一个引用指向某个局部对象,都会发生错误。因为局部对象在函数退出之前被销毁了,意味着reference所指的对象不存在。
      于是考虑在堆中创建   const Rational& operator* (const Rational& lhs, const Rational & rhs)
        {
            Rational*  result=new Rational(lhs.n*rhs.n,lhs.d*rhs.d);
            return *result;
        }
  现在又发现了一个问题,new出来的对象由谁来delete?好这个问题先占时不考虑看下面情况

          Rational w,x,y,z;
          w=x*y*z;    
  这里同时一个语句调用了两次operator*,意味着new了两次,也就需要delete两次。但是这里没有合理的办法让opertaor*使用者进行那些delete调用,因为无法让使用者获取返回的指针,这将导致资源泄漏。
      于是考虑返回一个引用,其指向定义于函数内部的static Rational对象。
      const Rational & operator*(const Rational& lhs,const Rational & rhs)
        {
            static Rational result;
            result = ...;
            return result;
        }
那么显而易见就是多线程,在多线程环境下,这样写安全吗?好如果说不关多线程。那么如下代码会发生什么?


  bool operator == (const Rational& lhs, const Rational&  rhs);

    ...

    Raional a,b,c,d;
    if((a*b) == (c*d) 
    {
            ...
    }
    上述if语句表达式无论a,b,c,d为何值都是true,因为它们都指向同一个静态值。

 

2、最好不要将所有变量定义放在语句开头。

有同学可能上过C语言课程,喜欢学习C的,喜欢将所有的变量定义放在开头,但是在C++中,我建议最好不要这样做,因为定义一个变量时,程序便注定需要进行一次构造与析构。例如在下面程序:大概意思我们允许1米8以下并且年龄在60岁以下的同学买票进入。


 1 class People{...};
 2 class Ticket{...};
 3 bool Isvalid(const People&p){...}
 4 void Banding(const People& p,Ticket& t); 
 5 Ticket buyTicket(const People& p)
 6 {
 7     Ticket t;
 8     if(Isvalid(p)){ return NULL };
 9     //信息与票绑定
10     Banding(p,&t);
11     return t;
12 }
假如这里检测买票人条件不符合,那么就不能进入买票从而进行信息与绑定操作,那么这里Ticket t语句就让该函数白白承受了一次Ticket构造成本与析构的成本。
所以最好不要将变量提前定义,最好在要用到的时候定义,避免不必要的性能开销。上面例子改成下面这样即可: 
 1 class People{...};
 2 class Ticket{...};
 3 bool Isvalid(const People&p){...}
 4 void Banding(const People& p,Ticket& t); 
 5 Ticket buyTicket(const People& p)
 6 {
 7     if(Isvalid(p)){ return NULL };
 8     Ticket t;
 9     //信息与票绑定
10     Banding(p,&t);
11     return t;
12 }
 

3、最好不要做过多的类型转换

C++规则的设计目标之一是,保证“类型错误”绝不可能发生。理论上程序通过编译,就表示它并不企图在任何身上执行任何不安全,荒谬的操作。可惜类型转换破环了类型系统,它可能导致任何种类麻烦,有些非常麻烦。就例如本文最后一个代码例子。C和C++都支持隐形类型转换,同时C++有四种显示转换操作符。成员函数与非成员函数的抉择里有介绍。但是建议最好不要做过多的类型转换,能避免就避免。类型转换往往也不是按照你的意思,首先看一个例子:


 1 #include <iostream>
 2 
 3 class base
 4 {
 5     public:
 6         base():a(0),b(0){}
 7         base(const int& x,const int& y)
 8         :a(x),b(y){}
 9         virtual void init()
10         {
11             a=5;
12             b=5;
13             std::cout<<"in base a value is "<<a<<std::endl;
14             std::cout<<"in base b value is "<<b<<std::endl;
15         }
16         
17         int get_a() const
18         {
19             return a;
20         }
21         
22         int get_b() const
23         {
24             return b;
25         }
26     private:
27         int a;
28         int b;
29 };
30 
31 class derived:public base
32 {
33     public:
34         derived(int x,int y):base(x,y){}
35         void init()
36         {
37             static_cast<base>(*this).init();
38         }
39 };
运行结果为

in base a value is 5
in base b value is 5
a value is 2
b value is 2
这里将derived类型转化为base,但是调用base::init()函数并不是当前对象上的函数,而是早前转型动作所建立的一个"*this对象的base的副本,所以当我们尝试改变对象内容,其实改变的是副本内容,其对象内容并没有被改变。

 如何解决这个问题呢?我们可以直接声明调用基类的函数


 1 class derived:public base
 2 {
 3     public:
 4         derived(int x,int y):base(x,y){}
 5         void init()
 6         {
 7             //static_cast<base>(*this).init();
 8             base::init();
 9         }
10 };
运行结果为:

in base a value is 5
in base b value is 5
a value is 5
b value is 5
或许此时你记起来应该使用dynamic_case(如果看过以前的文章的话:它用于安全地沿着继承关系向下进行类型转换)。使用dynamic_cast直接出现错误。


 1 class derived:public base
 2 {
 3     public:
 4         derived(int x,int y):base(x,y){}
 5         void init()
 6         {
 7             //static_cast<base>(*this).init();
 8             //base::init();
 9             dynamic_cast<base*>(this)->init();
10         }
11 };
运行结果为:

段错误 ((主存储器)信息转储)
假设一个类有五层的单继承关系,如果在该对象上执行dynaic_cast,那么会有多达五次的strcmp调用,深度或者多重继承的越多,成本越高。之所以需要dynamic_cast是因为想在derived class对象上执行 derived class操作函数,但是目前只有一个指向base的指针或者引用,这个时候可以用它们来处理。

C++ 一个函数调用其他.cpp文件中的函数 使用VC或VS创建C++项目的时候,会自动产生许多文件夹,其中有一个文件夹->源文件: 在该文件下可以自定义许多.cpp文件,但是需要注意的是这里面的各个文件只能有一个文件中含有main()函数, 而且各个文件中不能使用相同的函数名进行定义; 那么要那么多文件放在项目中有什么用呢? 当然这里C++是提供一个文件调用其他文件中函数的功能的, 这就可以让我们自定义一个只包含main()... 阅读详情

相关推荐

【RabbitMQ C++】AMQP-CPP实战:从零构建高效消息队列系统

本文详细介绍了如何使用C++和AMQP-CPP库从零构建高效的RabbitMQ消息队列系统。内容涵盖环境搭建、核心概念解析,并通过实战代码示例演示了如何编写生产者和消费者程序,实现消息的发布与订阅。文章重点讲解了如何与libev事件循环集成,以构建高性能、可靠的异步通信组件,为C++分布式系统开发提供了一套完整的解决方案。

5f4d3s2a1q的博客 933

C++你最好不要做的

1、最好不要使用引用返回值 有同学在传递的参数的时候使用引用方式传递,避免了临时对象的创建,提高了效率,那么在返回值的时候能不能使用引用呢? 看如下代码 class Rational{ public: Raional( int numerator = 0, int denominator =1); ...

dkenp04020的专栏 185

C++学习:0、CPP 学习概述

目录一、汇编的重要性1、学习建议2、代码本质的挖掘3、编程语言的本质区别二、开发环境的搭建 路线大纲: 常用语法: 面向对象: 项目实战: 特点: 通过反汇编,通过底层来观察 C++ 的本质 CPP 的应用领域 思考一个问题:既然 C ++ 执行效率这么高,为什么还要出现新的编程语言?所有地方都用 C++ 不就好了吗? 首先每一门编程语言都有自己的优缺点,都有自己的擅长的领域。 比如 python 适合数学家来进行算法开发,适合分析师进行数据分析,如果让数学家和分析师再学习C++ 那就太

vincent3678的博客 7709

C++应尽量使用的特性和应避免的特性

来源:《C专家编程》 尽量使用的C++特性: 类。 构造函数和析构函数,但只限于函数体非常简单的例子。 重载,包括操作符重载和I/O。 单继承和多态。 避免使用的C++特性: 模板。 异常。 虚基类(virtual base class)。 多重继承。 就我个人而言,异常的简单使用也没问题,其它的都很赞成此书的看法。写过一年的C++,似乎也只用到了...

jubincn的专栏 183

Dev-Cpp.zip:C++ IDE的安装与使用指南

Dev-Cpp作为一款广受欢迎的集成开发环境(IDE),在C++编程社区拥有着悠久的历史。尽管它不是最现代的IDE工具,但在开发者中依然有着坚实的拥趸。Dev-Cpp的核心组件包括:MinGW编译器:用于编译C/C++源代码。集成开发环境(IDE):提供代码编辑、编译和调试等集成工具。项目管理器:方便用户组织和管理多个项目。用户界面:提供图形化的操作环境。Dev-Cpp提供广泛的个性化设置选项,开发者可以根据自己的喜好和工作习惯对IDE进行配置。

weixin_33750664的博客 815

c++实际编程中应该注意的一些问题

c++实际编程中应该特别注意的一些问题 ,讲的很详细,设计到的面很光,几乎涵盖c++的编程中设计到的所有问题,讲解很细致,容易懂。

盘点那些C++中在写大型程序中最好不要滥用的语法排行榜

盘点那些C++中在写大型程序中最好不要滥用的语法排行榜

jinboxin_的博客 359

LangChain入门(二)-通过 Google 搜索并返回答案

并复制他给我们生成 api key。(博主使用了GitHub账号登录)-邮箱验证-手机号验证-订阅-api-key。Serpapi 提供了 google 搜索的 api 接口。首先需要我们到 Serpapi 官网上注册一个用户,

Good Luck 1万+

平时写c++程序需要注意什么

记一些几年前写c++经常会犯的一些错误,想到了其他的后面再加上 1、变量、函数命名不规范。 如果一个变量命名随意,比如表示一个学生的年纪,如果这样定义int a;相信一个月后自己再看代码,都不知道a表示什么意思, 如果用int age; 来表示,就清晰很多了。 再说函数,如果需要一个连接数据库的函数,写成connect();这是connect什么呢。如果写成connectDatabase()就很清晰了。 2、传递指针没有判断是否为空。传递对象、变量没有判断是否有效。 如果有一个接口是 void

c_shell_python的博客 1058

基于 OptiSystem 的掺铒光纤放大器(EDFA)分析

通过构建 EDFA 仿真模型,系统分析了铒离子掺杂半径、离子浓度、光纤长度及泵浦功率等关键参数对放大器增益和噪声特性的影响规律,为 EDFA 的优化设计提供了理论依据与仿真支撑。继续增大至 9μm,增益趋于稳定(约 19dB)。继续增加至 200mW,增益仅增加 2dB,表明泵浦功率存在阈值效应(约 100mW),超过后增益饱和明显。:作为增益介质,主要参数包括光纤长度(5~50m)、铒离子掺杂半径(1~10μm)、离子浓度(1×10²⁵~5×10²⁵m⁻³)、纤芯半径 2.2μm、数值孔径 0.24。

2501_91855190的博客 2676

保姆级教程:用Python+Mediapipe实时捕捉手势,驱动Unity虚拟手模型(附完整源码)

本文详细介绍了如何利用Python的Mediapipe库和Unity实现实时手势识别与虚拟手模型驱动。通过OpenCV进行图像采集,Mediapipe提供21个手部关键点识别,结合UDP通信协议实现Python与Unity之间的低延迟数据传输。教程包含完整源码、环境配置、核心代码实现及性能优化技巧,适用于VR教育、游戏开发等需要自然交互的场景。

weixin_42531779的博客 361

C++程序设计及注意事项

指的是在同一个域中,用同一个函数名来定义多个函数,但其参数类型应有不同,编译器将通过实参和形参的类型、个数等确定最佳匹配调用,不同类函数不采用函数重载。//声明一个max函数,其返回类型为int,两个输入为a,b,其类型均为int。多人编辑同一个项目时,一般在前面加static,使其只在某特定文件中使用,而不是全局,避免两人采用了同一函数名报错。6.C++允许为形参指定默认值,如果调用时该形参变量未给定实参值,则使用该形参值,如果给定了,则采用实参值。//采用以下方式,可以将后面定义的变量,在前面使用。

doudou2weiwei的博客 421

matlab生成blocks、bumps和doppler标准测试信号

关键函数:wnoise使用方式X = wnoise(FUN,N) [X,XN] = wnoise(FUN,N,SQRT_SNR) [X,XN] = wnoise(FUN,N,SQRT_SNR,INIT)X = wnoise(FUN,N) 返回由 FUN给出的信号,长度为2^N,幅值范围[0,1].[X,XN] = wnoise(FUN,N,SQRT_SNR) ,返回了一个测试信号X,以及一个加噪

ZSZ_shsf的博客 6580

JavaScript和C++的一些显著差异和学习tips

JS转C++的学习tips

Nesb01t is here. 250

从动态规划到最优控制:Hamilton-Jacobi-Bellman (HJB) 方程的核心思想与应用

本文深入解析了Hamilton-Jacobi-Bellman (HJB) 方程的核心思想与应用,从动态规划到最优控制的演变过程。通过实际案例展示了HJB方程在机器人路径规划、工业机械臂优化等领域的实践价值,并探讨了数值求解方法和深度学习结合的神经HJB前沿进展。

weixin_28700411的博客 458

Cadence psspxf实战:手把手教你仿真250MHz环形VCO的电源抑制比(附Verilog代码)

本文详细介绍了使用Cadence psspxf仿真器对250MHz环形VCO的电源抑制比(PSRR)进行仿真的全流程。从环形VCO的设计原理、Verilog代码实现,到Cadence环境配置、仿真参数设置,再到结果分析与优化技巧,提供了完整的实战指南。特别适合电路设计工程师学习如何评估和优化VCO的抗电源噪声能力。

weixin_42567752的博客 414

C++中.cpp和.hpp的区别

c++中 cpp和hpp 首先,我们可以将所有东西都放在一个.cpp文件内,编译器会将这个.cpp编译成.obj,即编译单元。一个程序可以由一个编译单元组成,也可以由多个编译单元组成。一个.cpp对应一个.obj,然后将所有的.obj链接起来(通过一个叫链接器的程序),组成一个.exe,即程序。如果一个.cpp要用到另一个.cpp定义的函数怎么办,只需在这个.cpp中写上它的函数声明。 链接器将所...

Qzx9059的博客 1万+

YOLO系列专栏(六):YOLO26热力图可视化 | 解析模型推理逻辑,定位检测关键区域

YOLO26作为新一代目标检测模型,其核心优势是高效的特征提取和精准的目标定位,但模型内部的推理过程的“黑盒”特性,给我们的优化带来了很大困扰:❌ 检测精度低:不知道是模型没学到关键特征,还是特征提取不充分;❌ 出现误检/漏检:无法定位问题根源——是锚框不合适?还是特征图未捕捉到目标?❌ 模型优化盲目:调参、修改网络结构全靠“猜”,缺乏针对性;❌ 难以解释模型行为:实际项目中,需要说明模型“为什么检测到这个目标”,尤其是医疗、工业等对可解释性要求高的场景。而热力图可视化。

qq_36130719的博客 732

从理论到实践:如何通过CPP-Crash-Course快速掌握C++编程技巧

**CPP-Crash-Course**是一个专为C程序员设计的C++快速入门教程项目,提供从基础语法到高级特性的完整学习路径。这个开源项目通过实用的代码示例和清晰的解释,帮助开发者快速从C语言过渡到现代C++编程,掌握面向对象编程、模板、异常处理等核心概念。无论你是刚接触C++的新手,还是希望系统复习C++知识的开发者,这个项目都能为你提供有价值的参考。 ## 📚 项目概述与核心价值 CP

gitblog_00617的博客 494

GPS天线结构、原理、测试

【有源陶瓷天线构成】GPS天线是由接收天线和前置放大器两个部件组成。GPS接收天线的作用,是将卫星来的无线电信号的电磁波能量变换成接收机电子器件可摄取应用的电流。绝大部分内置GPS天线为右旋极化陶瓷介质,其组成部分为:陶瓷天线、低噪音信号模块、线缆、[接头](h

数字世界 万物互联 2万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C++改写成C需要注意的几点

1.注释问题,C语言中"//"注释是非法的,解决方法:换成/**/的形式 2.C语言中没有BOOL类型       可以用int型替换                      typedef int bool;                      #define true 1                      #define TRUE 1          

大胖子的程序梦 1561

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【CPP】C++模板:初阶到进阶语法与实用编程示例

探索C++模板的深度与广度,《C++模板:初阶到进阶语法与实用编程示例》带您从基础语法起步,逐步深入到高级特性。本博客结合精炼的理论知识和丰富的代码实例,揭示模板编程的精髓,助您提升开发效率,优化代码结构。无论您是初学者还是资深开发者,都能在这里找到提升C++编程技能的宝贵资源。

BinaryWiker的博客 1380

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

c++的.h和.cpp文件

.h文件是不对外隐藏的, .cpp文件在编译后对外隐藏---这是最本质的特点和区别 .h和.cpp文件本质上是没有什么区别的,.h文件实现的功能是声明本文件或.cpp文件中需要被别人使用或知道的变量、类型、函数及宏定义等。.h文件就像是一个接口,具体的实现可以在.cpp中也可以在.h中。.cpp中的函数或变量即便是全局的,在没有其他.cpp文件使用的情况下,也可以不写在.h中。 下面参考:h...

小白博客 1万+

C++ 编程环境搭建与实践 —— 基于 comp-cpp 开源项目

C++ 编程环境搭建与实践 —— 基于 comp-cpp 开源项目 项目介绍 comp-cpp 是一个致力于简化 C++ 开发者编程环境配置的开源工具。它提供了便捷的方式让开发者快速搭建 C++ 开发环境,无论是对于初学者还是经验丰富的开发者,都能通过这个项目快速上手,进行代码编译与运行。该项目在 GitHub 上托管,允许社区成员贡献和改进,以适应更广泛的需求。 GitHub 仓库地址: htt...

gitblog_00367的博客 1150

关于C++语句的几点注意事项

关于C++语句的几点注意事项 main函数名的注意事项 int main()表明main()函数的返回值是整形,并将该值传送给调用它的函数,但是main()函数不会从调用它的函数获得任何信息。很多程序使用古典的C语言的函数名来代替: main()   //原来C语言的类型 在最初的C语言里,忽略返回值和说明该函数属于整形类型是同一个道理。但是,C++废除了这种用法。我们也可以使用下面这种变

u013252950的专栏 526

YOLOs-CPP:一个免费开源的YOLO全系列C++推理库(以YOLO26为例)

Python、Pytorch、C++、人工智能、Ultralytics、YOLO、ONNX、图像分类、目标检测、实例分割、旋转框检测、姿势估计

FriendshipTang的博客 2301
上一篇: C++文件依存关系
下一篇: C中的static修饰的镜头变量含义
myLogs
博客等级 码龄14年 6粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值