我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++中新手容易犯的十种编程错误汇总

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++中新手容易犯的十种编程错误汇总

前言

IT公司每年都会有一定的人员流动,相应地也会招一些应届生补充进来,指导应届生已经成为老员工的必修课了。平日里会我们会经常帮新人排查代码中的问题,在此过程中发现了C++新手容易犯的一些编程错误,在此简单的总结一下,给新人们提供一个参考。

1、有些关键字在cpp文件中多写了

对于C++类,一些关键字只要写在.h中就好,cpp中就不用再加上了,比如virtual、static等关键字,如果再cpp中多写,编译器会报错。比如如下的虚接口与静态成员变量的定义,只要在头文件中声明就可以了。


class shape
{
    virtual Draw();
    //...
    static int nLevel;
}

2、函数参数的默认值写到函数实现中了

带有参数默认值的函数,默认值是加在函数声明处的,函数实现处的参数是不需要带上的。为了方便查看代码,在函数实现处的参数中,将默认值注释起来。正确的做法是,头文件中有默认值:


BOOL CreateConf( const CString& strConfName, const BOOL bAudio = FALSE );

在函数实现处的参数中不用添加默认值:


BOOL CreateConf( const CString& strConfName, const BOOL bAudio );
{
    // ......
}

3、在编写类的时候,在类的结尾处忘记添加";"分号了

在类的结尾处忘记添加分号,编译会报错,新人们有可能找了半天也没找出引起编译错误的原因。其实很简单,在类的结尾处忘记添加分号了。


class Shape
{
    // ...
};

4、只添加了函数声明,没有函数实现

在添加类的函数时,只在类的头文件中添加了函数声明,但在cpp中却没有添加函数的实现。如果其他地方调用到该函数,在编译链接的时候会报 unresolved external symbol错误。因为没有实现,所有没有供链接使用的obj文件。

5、cpp文件忘记添加到工程中,导致没有生成供链接使用的obj文件

在添加C++类时,我们一般会添加.h头文件和一个.cpp源文件。结果忘记把.cpp文件添加到工程中了,即没有参与编译,没有生成供链接使用的obj文件。如果有代码调用到该C++类的接口,则在编译链接的时候会报 unresolved external symbol错误,即链接不到该C++类对应的接口。

6、函数中返回了一个局部变量的地址或者引用

在函数中返回了一个局部变量的地址或者引用,而这个局部变量在函数结束时其生命周期就结束了,内存就被释放了。当外部访问到该变量的内存,会触发内存访问违例的异常,因为该变量的内存已经释放了。比如如下的错误代码:


char* GetResult()
{
    char chResult[100] = { 0 };
 
    // ......
 
    return chResult;
}

7、忘记将父类中的接口声明virtual函数,导致多态没有生效

代码中本来要借助于C++多态的虚函数调用,调用子类实现的接口,结果忘记在父类中将对应的接口声明为virtual,导致没有调用到子类实现的函数。一定要记住,要实现多态下的函数调用,父类的相关接口必须声明为virtual。


class Shape()
{
    // ...
 
    virtual void Draw();
 
    // ...
} 

8、该使用双指针的地方,却使用了单指针

有时我们需要调用一个接口去获取某些数据,接口中将数据拷贝到传入的参数对应的内存中,此时设计参数时会传入指针或引用。我们在调用GetData之前定义了结构体指针p,并new出了对应的结构体对象内存,应该在定义GetData接口时应该使用双指针(指针的指针)的,结果错写成了单指针。

有问题的代码如下:


struct CodecInfo     // 编码信息
{
    int nFrameRate;
 
    // ...
}
 
 
CodecInfo* pInfo = new CodecInfo;
 
GetAudioCodecPtr()->GetCodecInfo(pInfo);   // 调用AudioCodec::GetCodecInfo获取编码信息
 
 
AudioCodec::GetCodecInfo( CodecInfo* pInfo)  // 此处的参数不应该使用单指针
{
    memcpy(pInfo, m_codecInfo, sizeof(CodecInfo));
}

上图中的AudioCodec::GetCodecInfo接口的参数不应该为单指针,应该用双指针,修改后的代码应该如下:


AudioCodec::GetCodecInfo( CodecInfo** pInfo)  // 此处的参数类型使用双指针
{
    memcpy(*pInfo, m_codecInfo, sizeof(CodecInfo));
}

9、发布exe程序时,忘记将exe依赖的C运行时库和MFC库带上

比如新人用VS-MFC库编写一个测试用的工具软件,结果在发布release版本程序时,没有将程序依赖的C运行时库带上,导致该工具软件在某些电脑中启动报错,提示找不到C运行时库:

因为程序中依赖了动态版本的运行时库和MFC库,在发布程序时要将这些库带上。有些系统中没有这些库,程序启动时就会报找不到库,就会启动失败。

10、应该使用深拷贝,却使用了浅拷贝

本来应该要进行深拷贝的,却使用了浅拷贝(直接赋值),导致另个不同生命周期的C++对象指向了同一块内存,一个对象将内存释放后,另一个对象再用到这块内存,就造成了内存访问违例,产生异常。

有个经典的C++笔试题,让我们实现String类的相关函数,其主要目的就是用来考察对深拷贝与浅拷贝的理解的。题目中给出String类的声明:


class String{
public:
    String();
    String(const String & str);
    String(const char* str);
    String& operator=(String str);
    char* c_str() const;
    ~String();
    int size() const;
private:
    char* data;
};

让写出上述几个函数的内部实现。这些函数的实现代码如下:


//普通构造函数  
String::String(const char *str)
{
 if (str == NULL)
 {
  m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志'\0'的,加分点:对m_data加NULL判断  
  *m_data = '\0';
 }
 else
 {
  int length = strlen(str);
  m_data = new char[length + 1];// 若能加 NULL 判断则更好
  strcpy(m_data, str);
 }
}
 
 
// String的析构函数  
String::~String(void)
{
 delete[] m_data; // 或delete m_data;  
}
 
 
//拷贝构造函数  
String::String(const String &other)// 得分点:输入参数为const型  
{   
 int length = strlen(other.m_data);
 m_data = new char[length + 1];// 若能加 NULL 判断则更好  
 strcpy(m_data, other.m_data);
}
 
 
//赋值函数  
String & String::operator = (const String &other) // 得分点:输入参数为const型  
{
 if (this == &other)//得分点:检查自赋值  
  return *this; 
 if (m_data)
     delete[] m_data;//得分点:释放原有的内存资源  
 int length = strlen(other.m_data);
 m_data = new char[length + 1];//加分点:对m_data加NULL判断  
 strcpy(m_data, other.m_data);
 return *this;//得分点:返回本对象的引用    
}

总结

到此这篇关于C++中新手容易犯的十种编程错误的文章就介绍到这了,更多相关C++新手易犯编程错误内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++中新手容易犯的十种编程错误汇总

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

下载Word文档

猜你喜欢

C#编程中最容易犯的7种编写错误分享

编程时犯错是必然的,这篇文章主要和大家来分享7个C#编程中最容易犯的7种编写错误,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
2023-03-01

Python新手入门最容易犯的错误总结

前言 Python 以其简单易懂的语法格式与其它语言形成鲜明对比,初学者遇到最多的问题就是不按照 Python 的规则来写,即便是有编程经验的程序员,也容易按照固有的思维和语法格式来写 Python 代码,之前小编给大家分享过了一篇《Pyt
2022-06-04

Python新手们容易犯的几个错误总结

前言 这篇文章主要给大家总结了关于学习Python的新手们容易犯的几个错误,一共四个易犯错误,下面来看看详细的介绍吧。 一、i+=1 不等于++i 初学者对Python语言不是特别了解的话,又正好有c++,java的语言背景,很容易把++i
2022-06-04

C#编程中最容易犯的编写错误有哪些

这篇文章主要讲解了“C#编程中最容易犯的编写错误有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#编程中最容易犯的编写错误有哪些”吧!1、拼接字符串在C#编程中,字符串类型的处理是比较
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录