C/C++程序员需要注意的11个知识点(转)

C/C++编程笔记:C语言字符串转换知识点!字符转数字,数字转字符 在C/C++语言中没有专门的字符串变量,通常用字符数组来存放字符串。字符串是以“\0”作为结束符。C/C++提供了丰富的字符串处理函数,下面列出了几个最常用的函数。 ● 字符串输出函数puts。 ● 字符串输出函数gets。 ● 字符串连接函数strcat。 ● 字符串复制函数strcpy。 ● 测字符串长度函数strlen。 字符串是面试的重点考查部分的相关知识,通过考查字符串的相关知识可以考察程序员的编程规范以及编程习惯。并且其中包括了许多知识点,例如内存越界、指针与数组操作等。许多公司 阅读详情

下面的这些要点是对所有的C++程序员都适用的。我之所以说它们是最重要的,是因为这些要点中提到的是你通常在C++书中或网站上无法找到的。如:指向成员的指针,这是许多资料中都不愿提到的地方,也是经常出错的地方,甚至是对一些高级的C++程序员也是如此。
这里的要点不仅仅是解释怎样写出更好的代码,更多的是展现出语言规则里面的东西。很显然,它们对C++程序员来说是永久的好资料。我相信这一篇文章会使你收获不小。
首先,我把一些由不同层次的C++程序员经常问的问题归到一起。我惊奇的发现有很多是有经验的程序员都还没意识到 .h 符号是否还应该出现在标准头文件中。
要点1: <iostream.h> 还是 <iostream>?
很多C++程序员还在使用<iostream.h>而不是用更新的标准的<iostream>库。这两者都有什么不同呢?首先,5年前我们就开始反对把.h符号继续用在标准的头文件中。继续使用过时的规则可不是个好的方法。从功能性的角度来讲,<iostream>包含了一系列模板化的I/O类,相反地<iostream.h>只仅仅是支持字符流。另外,输入输出流的C++标准规范接口在一些微妙的细节上都已改进,因此,<iostream>和<iostream.h>在接口和执行上都是不同的。最后,<iostream>的各组成都是以STL的形式声明的,然而<iostream.h>的各组成都是声明成全局型的。
因为这些实质上的不同,你不能在一个程序中混淆使用这两个库。做为一种习惯,在新的代码中一般使用<iostream>,但如果你处理的是过去编写的代码,为了继承可以用继续用<iostream.h>旧保持代码的一致性。
要点2:用引用传递参数时应注意的地方  
在用引用传递参数时,最好把引用声明为const类型。这样做的好处是:告诉程序不能修改这个参数。在下面的这个例子中函数f()就是传递的引用:
void f(const int & i);
int main()
{
f(2); /* OK */
}
这个程序传递一个参数2给f()。在运行时,C++创建一个值为2的int类型的临时变量,并传递它的引用给f().这个临时变量和它的引用从f()被调用开始被创建并存在直到函数返回。返回时,就被马上删除。注意,如果我们不在引用前加上const限定词,则函数f()可能会更改它参数的值,更可能会使程序产生意想不到的行为。所以,别忘了const。这个要点也适用于用户定义的对象。你可以给临时对象也加上引用如果是const类型:
struct A{};
void f(const A& a);
int main()
{
f(A()); // OK,传递的是一个临时A的const引用
}  
要点3:“逗号分离”表达形式
“逗号分离”表达形式是从C继承来的,使用在for-和while-循环中。当然,这条语法规则被认为是不直观的。首先,我们来看看什么是“逗号分离”表达形式。
一个表达式由一个或多个其它表达式构成,由逗号分开,如:
if(++x, --y, cin.good()) //三个表达式  
这个if条件包含了三个由逗号分离的表达式。C++会计算每个表达式,但完整的“逗号分离”表达式的结果是最右边表达式的值。因此,仅当cin.good()返回true时,if条件的值才是true。下面是另一个例子:  
int j=10;  
int i=0;
while( ++i, --j)
{
//直到j=0时,循环结束,在循环时,i不断自加
}  
要点4,使用全局对象的构造函数在程序启动前调用函数
有一些应用程序需要在主程序启动前调用其它函数。如:转态过程函数、登记功能函数都是必须在实际程序运行前被调用的。最简单的办法是通过一个全局对象的构造函数来调用这些函数。因为全局对象都是在主程序开始前被构造,这些函数都将会在main()之前返回结果。如:  
class Logger
{
public:
Logger()  
{  
activate_log();//译者注:在构造函数中调用你需要先运行的函数
}
};
Logger log; //一个全局实例
int main()
{
record * prec=read_log();//译者注:读取log文件数据
//.. 程序代码
}
全局对象log在main()运行之前被构造,log调用了函数activate_log()。从而,当main()开始执行时,它就可以从log文件中读取数据。
毫无疑问地,在C++编程中内存管理是最复杂和最容易出现bug的地方。直接访问原始内存、动态分配存储和最大限度的发挥C++指令效率,都使你必须尽力避免有关内存的bug。
要点5:避免使用复杂构造的指向函数的指针
指向函数的指针是C++中可读性最差的语法之一。你能告诉我下面语句的意思吗?  
void (*p[10]) (void (*)());  
P是一个“由10个指针构成的指向一个返回void类型且指向另一个无返回和无运算的函数的数组”。这个麻烦的语法真是让人难以辨认,不是吗?你其实可以简单的通过typedef来声明相当于上面语句的函数。首先,使用typedef声明“指向一个无返回和无运算的函数的指针”:  
typedef void (*pfv)();  
接着,声明“另一个指向无返回且使用pfv的函数指针”:  
typedef void (*pf_taking_pfv) (pfv);  
现在,声明一个由10个上面这样的指针构成的数组:  
pf_taking_pfv p[10];  
与void (*p[10]) (void (*)())达到同样效果。但这样是不是更具有可读性了!  
要点6:指向成员的指针
一个类有两种基本的成员:函数成员和数据成员。同样的,指向成员的指针也有两种:指向函数成员的指针和指向数据成员的指针。后则其实并不常用,因为类一般是不含有公共数据成员的,仅当用在继承用C写的代码时协调结构(struct)和类(class)时才会用到。
指向成员的指针是C++语法中最难以理解的构造之一,但是这也是一个C++最强大的特性。它可以让你调用一个类的函数成员而不必知道这个函数的名字。这一个非常敏捷的调用工具。同样的,你也可以通过使用指向数据成员的指针来检查并改变这个数据而不必知道它的成员名字。

指向数据成员的指针
尽管刚开始时,指向成员的指针的语法会使你有一点点的迷惑,但你不久会发现它其实同普通的指针差不多,只不过是*号的前面多了::符号和类的名字,例:定义一个指向int型的指针:
int * pi;   
定义一个指向为int型的类的数据成员:  
int A::*pmi; //pmi是指向类A的一个int型的成员  
你可以这样初始化它:  
class A
{
public:
int num;
int x;
};
int A::*pmi = & A::num;   
上面的代码是声明一个指向类A的一个int型的num成员并将它初始化为这个num成员的地址.通过在pmi前面加上*你就可以使用和更改类A的num成员的值:  
A a1, a2;
int n=a1.*pmi; //把a1.num赋值给n
a1.*pmi=5; // 把5赋值给a1.num  
a2.*pmi=6; // 把6赋值给6a2.num  
如果你定义了一个指向类A的指针,那么上面的操作你必须用 ->*操作符代替:  
A * pa=new A;
int n=pa->*pmi;  
pa->*pmi=5;   
指向函数成员的指针
它由函数成员所返回的数据类型构成,类名后跟上::符号、指针名和函数的参数列表。举个例子:一个指向类A的函数成员(该函数返回int类型)的指针:
class A  
{
public:
int func ();  
};  
int (A::*pmf) ();  
上面的定义也就是说pmf是一个指向类A的函数成员func()的指针.实际上,这个指针和一个普通的指向函数的指针没什么不同,只是它包含了类的名字和::符号。你可以在在任何使用*pmf的地方调用这个函数  
func():
pmf=&A::func;
A a;
(a.*pmf)(); //调用a.func()  
如果你先定义了一个指向对象的指针,那么上面的操作要用->*代替:  
A *pa=&a;
(pa->*pmf)(); //调用pa->func()  
指向函数成员的指针要考虑多态性。所以,当你通过指针调用一个虚函数成员时,这个调用将会被动态回收。另一个需要注意的地方,你不能取一个类的构造函数和析构函数的地址。
要点7、避免产生内存碎片
经常会有这样的情况:你的应用程序每运行一次时就因为程序自身缺陷而产生内存漏洞而泄漏内存,而你又在周期性地重复着你的程序,结果可想而知,它也会使系统崩溃。但怎样做才能预防呢?首先,尽量少使用动态内存。在大多数情况下,你可能使用静态或自动存储或者是STL容器。第二,尽量分配大块的内存而不是一次只分配少量内存。举个例子:一次分配一个数组实例所需的内存,而不是一
次只分配一个数组元素的内存。
要点8、是delete还是delete[]
在程序员中有个荒诞的说法:使用delete来代替delete[]删除数组类型时是可以的!
举个例子吧:
int *p=new int[10];
delete p; //错误,应该是:delete[] p  
上面的程序是完全错误的。事实上,在一个平台上使用delete代替delete[]的应用程序也许不会造成系统崩溃,但那纯粹是运气。你不能保证你的应用程序是不是会在另一个编译器上编译,在另一个平台上运行,所以还是请使用delete[]。
要点9、优化成员的排列
一个类的大小可以被下面的方式改变:
struct A
{
bool a;
int b;
bool c;
}; //sizeof (A) == 12
在我的电脑上sizeof (A) 等于12。这个结果可能会让你吃惊,因为A的成员总数是6个字节:1+4+1个字节。那另6字节是哪儿来的?编译器在每个bool成员后面都插入了3个填充字节以保证每个成员都是按4字节排列,以便分界。你可以减少A的大小,通过以下方式:
struct B
{
bool a;
bool c;
int b;
}; // sizeof (B) == 8
这一次,编译器只在成员c后插入了2个字节。因为b占了4个字节,所以就很自然地把它当作一个字的形式排列,而a和c的大小1+1=2,再加上2个字节就刚好按两个字的形式排列B。   
要点10、为什么继承一个没有虚析构函数的类是危险的?
一个没有虚析构函数的类意味着不能做为一个基类。如std::string, std::complex, 和 std::vector 都是这样的。为什么继承一个没有虚析构函数的类是危险的?当你公有继承创建一个从基类继承的相关类时,指向新类对象中的指针和引用实际上都指向了起源的对象。因为析构函数不是虚函数,所以当你delete一个这样的类时,C++就不会调用析构函数链。举个例子说明:
class A
{
public:
~A() // 不是虚函数
{
// ...
}
};  
class B: public A //错; A没有虚析构函数
{
public:
~B()
{
// ...
}
};
int main()
{
A * p = new B; //看上去是对的
delete p; //错,B的析构函没有被调用
}
要点11、以友元类声明嵌套的类
当你以友元类声明一个嵌套的类时,把友元声明放在嵌套类声明的后面,而不前面。
class A  
{
private:
int i;
public:
class B //嵌套类声明在前
{
public:
B(A & a) { a.i=0;};  
};
friend class B;//友元类声明
};
如果你把友元类声明放在声明嵌套类的前面,编译器将抛弃友元类后的其它声明。  

C/C++程序的断点调试 - Dev C++ 本文以Dev C++ 5.11为例,简述C/C++程序断点调试的基本方法和过程。其它的IDE环境,大同小异。 阅读详情

相关推荐

windows11下vscode配置C/C++(过程记录)

使用vscode编写编译C++文件,需要在里面添加如下的文件,如图所示。需要建立.vscode文件夹,下面一共有四个文件,如下所示。可以使用vscode让软件帮忙生成,也可以直接手动建立。直接手动建立比较快速。这里我选择直接手动建立四个文件。tasks.json下面将分别说明这四个文件里面的内容是什么。

GFCLJY的博客 2814

C++编码注意的细节

下面的这些要点是对所有的C++程序员都适用的。我之所以说它们是最重要的,是因为这些要点中提到的是你通常在C++书中或网站上无法找到的。如:指向成员的指针,这是许多资料中都不愿提到的地方,也是经常出错的地方,甚至是对一些高级的C++程序员也是如此。 这里的要点不仅仅是解释怎样写出更好的代码,更多的是展现出语言规则里面的东西。很显然,它们对C++程序员来说是永久的好资料。我相信这一篇文章会使你收

工作、生活 600

从C/C++到Go

       很多程序员都是从c/c++转到go的,难免会产生一些混淆, 在学习go语言的时候,尤其要注意与c/c++的区别, 对比起来学习效果可能更好。下面这个总结很不错, 直接引用过来学习:http://hyperpolyglot.org/c   Hyperpolyglot C, Go a side-by-side reference sheet grammar and invoca...

认知 行动 坚持 7536

C++ 编码注意事项

1. const函数, 声明和定义都需要加const,  函数名 const {}

u013985241的博客 339

UART全功能测试指南:环路/DMA/RS485/硬件流控实战

UART(通用异步收发器)是嵌入式系统中最基础的串行通信接口,其核心原理基于起始位、数据位、校验位与停止位的异步帧结构,依赖精确的波特率时钟同步与采样重建机制。在工业与物联网场景中,UART不仅需保障基本通信可靠性,更需支持DMA卸载、RS485半双工自动方向控制、RTS/CTS硬件流控等进阶能力,以提升实时性、抗干扰性与系统资源效率。典型应用涵盖调试日志输出、传感器数据采集、Modbus RTU总线通信及固件空中升级。本指南聚焦UART外设测试实践,覆盖环路自检、DMA吞吐验证、RS485时序对齐、硬件流

weixin_42599908的博客 133

基于ST32 DAC7311数模转换器驱动代码及电路设计完整版

基于ST32的DAC7311模数转换器的电路设计及驱动代码完整版

qq_39626643的博客 3720

关于C++在编码时的一些细节

函数不能依赖于filescope对象,否则会造成重用困难 默认参数右侧的参数也必须为默认定义(函数定义,类定义)只能有一个,否则编译时没有问题,link时报有多个定义声明 (变量,函数名)只能有一个,否则编译时会报symbol redefineinline是在编译时展开,所以要在头文件中定义,否则在编译时无法展开。写在CPP中的定义是用来link的。含非inline函数的头文件被多次包含,lin

最爱吹吹风 326

ansys命令流力磁耦合仿真

文章目录前言一、力磁耦合仿真流程二、静力学仿真三、力磁耦合模型构建四、静磁学仿真总结 前言 一、力磁耦合仿真流程 力磁耦合有限元仿真流程中,首先进行静力学仿真,经过前处理模块、分析计算模块和后处理模块提取三维模型单元应力,然后根据力磁耦合方程中,通过matlab将单元应力导入到磁导率与应力的关系式中,得到单元的相对磁导率。最后采用载荷传递耦合方式,进行静磁学模拟仿真,分析计算得到该载荷下试件的磁场分布。,如下图所示为力磁耦合仿真流程图: 二、静力学仿真 下图为中心预制条形缺陷的Q235钢板试..

wsfwsf128的博客 2662

C++中的各种小细节(三)

十一、创建数组的两种形式 形式一: #define N 10 int a[N]; int n = 10; int b[n];//编译报错 注意这种定义数组的形式有很多缺点,例如:1:数组的长度必须是在编译时就知道的,即数组的长度不能改变, 在定义数组指定数组的长度值必须为一个常量值,2:数组只在定义它的语句块内存在,因为这种形式属于是编译器 自动在栈内

YYC的专栏 1196

STM32F4驱动ES8388音频芯片的I²S时钟与DMA流设计

I²S(Inter-IC Sound)是一种广泛应用于嵌入式音频系统的同步串行总线协议,其核心在于精确的时钟同步与稳定的数据流传输。理解I²S时钟树结构(含MCLK、SCLK、WS生成逻辑)和分频机制,是保障CD级音质(如44.1kHz/16bit)的基础;而DMA双缓冲技术则解决了实时音频播放中数据供给连续性的关键工程问题。在STM32F4等Cortex-M4平台中,需协同配置PLLI2S锁相环、I²S预分频寄存器(I2SxPR)及DMA循环模式,同时兼顾ES8388等Codec芯片的I²C初始化时序与寄

weixin_35390379的博客 244

Dify 本地插件安装失败?别慌,这篇教程手把手教你解决(解决 the plugin you want to install has a bad signature 报错的问题)

🤯dify安装本地插件报错 PluginDaemonBadRequestError: plugin verification has been enabled, and the plugin you want to install has a bad signature。的解决方案!

XiaoqiangClub的博客 3985

统一文件编码和代码风格,提高代码可读性

模板文件codetemplates.xml和formatter.xml在附件中formater.zip 1.由菜单Window -&gt;Preference打开Eclipse配置界面 2.设置代码模板JAVA-&gt;Code Style -&gt; Code template -&gt;import 导入代码模板codetemplates.xml 点击edit 修改3.设置formaterJ...

zw7534313的专栏 438

白话机器学习算法理论+实战番外篇之Xgboost

1. 写在前面 如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,在这简单的先捋一捋, 常见的机器学习算法: 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Adaboost等 无监督算法:聚类,降维,关联规则, PageRank等 我前面已经尝试用最白话的语言完成了一个白话机器学习算法理论+实战系列,这个系列已经基本包含了上面这些算...

Miracle8070 1万+

C/C++基础知识点面试题

目录 一、虚函数的数据结构,如何工作? 二、const与define的区别? 三、指针与引用的区别? 四、指针与数据的区别? 五、不用临时变量实现两个变量的交换 七、一个C++源文件从文本到可执行文件经历的过程 八、C++11新特性 九、C++和C的不同 十、malloc的原理 十一、内存泄漏、野指针 十二、static 十三、union和struct 十四、new与ma...

找个特立不独行的名的博客 2万+

【WorkBuddy专栏25】如何选择大模型——积分消耗、用途场景、选型决策全指南

【WorkBuddy专栏25】如何选择大模型——积分消耗、用途场景、选型决策全指南

AI人人懂 940

第182期 Claude Skills:深入探究Anthropic的智能体框架(一篇彻底讲透彻)

摘要: Claude Skills是Anthropic推出的智能体框架,通过连接外部工具和服务扩展Claude AI的功能,支持实时交互与任务执行。其核心架构包含技能路由器、注册表、执行引擎等模块,采用渐进式披露机制优化上下文管理。与MCP和A2A相比,Skills更注重模块化设计与Claude深度集成,通过SKILL.md文件定义可重复工作流程,兼具高效性和灵活性。开发者可创建自定义技能,遵循聚焦用户价值、安全隐私等最佳实践,实现AI能力的场景化拓展。该框架与MCP、A2A形成互补,共同推动智能体生态发展

全网120W+关注AI拉呱,专注人工智能以及科技前沿! 2132

企业对C/C++程序员的技能要求

一个人应该具备对事物的思考能力,否则容易被忽悠。对大部分未入门或刚入门的菜鸟来说,很难搞明白C语言能做什么和C程序员在做什么这两个问题。 如果你打算种菜,必须先了解行情(包括销量和价钱),如果你打算学习C语言,也应该先了解C程序员的行情。 了解青菜的行情要去菜市场,了解C程序员的行情要去人才市场。 我们先来查一些资料。 C语言与...

C语言技术网-码农有道 3904

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

vscode配置c++11

1.vscode默认c++98 在macos安装vscode以后,默认的c++版本为98。这个版本相对比较老,对很多新特性新语法也不支持。比如如果我们使用如下增强型for循环 for(int n: listnum) {...} vscode会提示: range-based for loop is a C++11 extension [-Wc++11-extensions] 因此,我们需要将vscode中的c++版本进行设置。 2.tasks.json配置c++11 tasks.json是对编译进行相关配

bitcarmanlee的博客 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C/C++容易混淆的小知识点

1、函数传指针和传引用的区别? 1>指针定义时可以不初始化,但引用不行; 2>引用只能和一个实体结合,而指针可和多个实体结合; 3>自加减意义不同。指针的++表示指针向后偏移类型个字节,而引用则是+1,–类似; 4>sizeof求值的意义不同。Sizeof(指针)是指针所占的字节数,32位平台下为4,64位平台下为8(数组名除外),sizeof(引用)是指引用所指实体类型的大小; 5>没有

snow_5288的博客 3019

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C/C++编译器-Dev-Cpp 5.11安装教程(含资源)

C/C++编译器-Dev-Cpp 5.11安装教程(含资源) 去发现同类优质开源项目:https://gitcode.com/ 简介 本资源文件提供了Dev-Cpp 5.11版本的安装教程及相关资源下载。Dev-Cpp是一款轻量级的C/C++集成开发环境(IDE),适合初学者和专业开发者使用。本教程将指导您如何安装和配置Dev-Cpp 5.11,以便您能够快速开始C/C++编程。 安装步骤 1. ...

gitblog_06552的博客 616

C/C++版本更迭历程

文章目录前言C语言版本更迭C++版本更迭号外号外C/C++标准gcc/g++ 前言 使用 C/C++ 实现功能的时候经常需要上网搜索一些解决方案,但是当你把代码粘贴到自己项目中时偶尔会出现编译失败的问题,其中一个原因就是新加的代码所使用的特性在当前的编译环境中并不支持,就好像不久前我们还在使用VS2003写着C++98标准的代码(2015年),虽然对C++11的特性垂涎已久,但是无奈在项目中就是无...

AlbertS Home of Technology 2万+

视频教程-C/C++程序员实战基础-C/C++

C/C++程序员实战基础 我是职业的程序员,不是职业的讲师,我可能表达不流畅...

weixin_33395743的博客 1089

【免费下载】 C11/C++11 标准中文版下载

C11/C++11 标准中文版下载 【下载地址】C11C11标准中文版下载 C11/C++11 标准中文版下载 项目地址: https://gitcode.com/open-source-toolkit/0f1da ...

gitblog_09814的博客 2290

C/C++(八)C++11

本文将介绍继C++98以来更新最大的一个标准,也是实际开发中用的最多的重要标准,C++11标准。由于C++11增加了非常多的语法特性,笔者学识有限,也很难一一介绍,在此主要讲解一些比较实用的语法。

m0_73682725的博客 1157

C/C++知识点总结

C++笔试知识点总结(语法及常用函数)输入输出C++中的new/deletevector 输入输出 (1) 第一行输入两个整数M,N;接下来M行分别输入2个数,最后一行输入N个数(由于输入行数,个数都确定,用循环很好处理) (2)循环输入多行 while(cin>>m>>n){ } (3)输入一行数字,数字间以空格分隔 #include<sstream> in.........

LilyZJ的博客 1429
上一篇: 成为一名优秀程序员所需要知道的那些事(转载)
下一篇: 在Fedora 14 搭建Android 开发环境
kaffeel
博客等级 码龄17年 56粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值