C++primerplus

简介: C++primerplus

您可能想将一些用C或者老式C++版本开发的程序转换为标准C++,本附录提供了这方面的一些指南,其中的一些内容是关于从C转换为C++的,另一些是从老式C++准欢换为标准C++的
1.1使用一些预处理编译器编译指令的替代品
C/C++预处理器提供了一系列的编译指令,通常,C++惯例是使用这些编译指令来管理的编译过程,而避免用编译指令替换代码,例如,#include编译指令是管理程序文件的重要组件,其他编译指令如#ifndef和#endif使得能够控制是否对特定的代码块进行编译,#pragma编译指令能够控制编译器特定的编译选项,这些都是非常有帮助有时是必不可少的工具,但使用#define编译指令时应谨慎。
1.1.1 使用const而不是#define来定义常量
符号常量可提高代码的可读性和可维护性,常量名指出来了其含义,如果想要修改它的值,只需定义修改一次,然后从新编译即可,C使用预处理器来创建常量的符号名称。

define MAX_LENGTH 100

这样,预处理器将在编译之前对源代码执行文本置换,即用100替换所有的MAX_LENGTH.
而C++则在变量声明使用限定符const
const intMAX_LENGTH = 100;
这样MAX_LENGTH将视为一个只读的int变量
使用const 方法有很多优越性,首先,声明显式指明了类型,使用#define时,必需在数字后加上各种后缀来指出除char、int或者double之外的类型,例如,使用100L来表明long类型,使用3.14F来表明float类型,更重要的是,const方法可以很方便地用于复合类型,如下例所示,:
const int base_vals{5} = {100,2000,3500,6000,10000};
const string ans[3] = {"yes","no","maybe"};
最后,const标识符遵循变量的作用域规则,因此,可以创建作用域为全局、名称空间或数据块的常量,在特定函数中定义常量时,不必担心其定义会与程序的其他地方使用的全局变量冲突,例如,对于下面的代码:

define n 5

const int dz = 12;

void fizzle()
{
int n ;
int dz;

}
预处理器将把:
int n;
替换为:
int 5;
从而导致编译错误,而fizzle()中定义的dz是本地变量,另外,必要时,fizzle()可以使用作用域解析
操作符(::),以::dz的方式访问该常量。
虽然C++借鉴了C语言中的关键字const,但C++版本更有用,例如对于外部const
值,C++版本有内部链接,而不是变量和C中const所使用的默认外部链接,这意味着使用const
的程序中的每个文件都必需定义该const,这好像增加了工作量,但实际上它使工作更简单,使用内部链接时,可以将const定义放在工程中的各种文件使用的头文件中,对于外部链接,这将导致编译错误,但对于内部链接,情况并非如此,另外由于const必须在使用它的定义中定义,在该文件使用的头文件中,对于外部链接,这将导致编译错误,但对于内部链接,情况并非如此,另外由于const必须在使用它的定义(在该文件使用的头文件中定义也满足这样的需求)因此可以将const值用作数组长度参数
const int MAX_LENGTH = 100;
double loads[MAX_LENGTH];
for(int i =0;int<MAX_LENGTH;i++)
loads[i] = 50;
这在C中是行不通的,因为定义MAX_LENGTH的声明可能位于一个独立的文件中,在编译中,该文件可能不可用,坦白地说,在C中,可以使用static限定符来创建内部链接常量,这就是说,C++通过默认使用static,让您可以少记住一件事。
顺便说一句,修订后的C标准,C99,允许const用作数组长度,但必须将数组作为一种新式数组---变量数组,而这不是C++标准的一部分。
在控制何时编译头文件方面,#define编译指令仍然很有帮助:
//blooper.h

ifndef _BLOOPERH

define _BLOOPERH

//code goes here

endif

但对于符号常量,习惯上还是使用const,而不是#define,另一个好方法---尤其是在有一组相关的整型常量时,是使用enum;
enum{LEVEL} = 1.LEVEL2=2,LEVEL3=4,LEVEL4=8};
1.1.2使用inline而不是#define来定义小型函数
在创建类似于内联函数的东西时,传统的C语言方式是使用一个#define另一个好方法--尤其是在有一组相关的整型常量时----是使用enum;
enum[LEVEL] = 1.LEVEL2=2.LEVEL3=4.LEVEL4=8};
1.1.2使用inline而不是#define来定义小型函数
在创建类似于内联函数的东西时,传统的C语言是使用#define宏定义:

define Cube(X)XXX

这将导致预处理器进行文本置换,将X替换为Cube()的参数:
y=Cube(X);//replaced with y = xx
这将导致预处理器进行文本置换,将X替换为Cube()的参数
由于预处理器使用文本置换,而不是真正的传递参数,因此使用这种宏可能导致意外的错误的结果,要避免这种错误,可以在宏中使用大量的圆括号来确保正确的运算顺序。

define Cube (X) ((X)(X)*(X))

但即使这样做,也无法处理使用诸如Z++等值的情况
C++方法是使用关键字inline来标识内联函数,这种方法更可靠,因为它采用的是真正的参数传递,
另外,C++内联函数可以是常规函数,也可以是类方法
class dormant
{
private :
int peroid:

public :
int Peroid()const {
return peroid;
}//automatically inline

};

define宏的一个优点是,它是无类型的,因此将其用于任何类型,运算都是有意义的,在c++中,可以创建内联函数模板来使函数独立于类型,同时传递参数

简而言之,请使用C++内敛技术,而不是C语言中的#define宏
1.2使用函数原型
实际上,您没有选择的余地,虽然在C中,原型是可选的,,但是在C++中,它确实是必不可少的 ,请注意,在被使用之前定义的函数,如内联函数,是其原型
应尽可能在函数原型和函数头中使用const,具体的说,对于表示不可修改的数据的指针参数和引用参数,应使用const,这不仅使编译器能够捕获修改数据的错误,也使函数更为通用,也就是说,接受const指针或者引用函数能够同时处理const数据和非const数据,而不使用const指针或饮用的函数只能处理非const数据
1.3使用类型转换
stroustrap对c语言的抱怨之一是其无规律可循的类型转换操作符,,确实,类型转换通常是必需的,但标准类型转换太不严格,例如,对于下面的代码
struct Doof{
double feeb;
double steeb;
char sqif[10]
};
Doof leam;
short ps = (short )&leam//old syntax
int pi = int
(&leam);//new syntax
1.4逐渐熟悉C++特性
如果使用的是malloc()和free(),请改用new和delete;如果使用setjmp()和longjmp()处理错误,则请改用trythrow和catch.另外对于标识true和false的值,则将其类型声明为bool。
1.5使用新的头文件
c++标准指定了头文件的新名称,请参见第2章,如果使用的是老式头文件,则应当改用新名称。
这样做不仅仅是形式上的改变,因为新版本有时增强了特性,例如头文件ostream提供了对宽字符输入和输出的支持,还提供了新的操纵符,如boolalpha和fixed(请参见第17章)对于众多格式化选项的设置来说,这些操纵符符合提供的接口

1.6使用名称空间
名称空间有助于组织程序中使用的标识符,避免名称冲突,由于标准库是使用新的头文件组织实现的,它将名称放在std名称空间中,因此使用这些头文件需要处理名称空间
出于简化的目的,本书的范例都使用编译指令using 来使std 名称空间中的名称可用

include

include

include

using namespace std;//a using directive
不过,不管需要与否,都导出名称空间中的所有名称,是与名称空间的初衷背道而驰的。
稍微要好些的方法是,在函数中使用using编译指令,这将使名称在该函数中可用,
更好也是推荐的方法是,使用using声明或作用域解析操作符(::),只使程序需要的名称可用,例如,下面的代码:

include

using std:::cin; //a using declaration
using std::cout;
using std::endl;

使cin、cout和end1可用于文件的剩余部分,但使用作用域解析操作符只能使名称在使用该操作符的表达式中可用
cout<<std::fixed<<x<<endl;//using the Scope resolution operation

这样做可能很麻烦,但可以将通用的using 声明放在一个头文件中;
//mynames--a header file
using std::cin;
using std::cout;
using std:endl;
还可以将通用的using声明放在一个名称空间中
//mynames --a header file

include

目录
相关文章
|
6月前
|
机器学习/深度学习 运维 算法
[WWW2024]轻量数据依赖的异常检测重训练方法LARA
阿里云计算平台大数据基础工程技术团队主导,与浙江大学合作的论文《LARA: ALight and Anti-overfitting Retraining Approach for Unsupervised Time Series Anomaly Detection 》被WWW2024收录
|
2天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
4天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
5234 18
|
16天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
8天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
4天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
8天前
|
Cloud Native Apache 流计算
PPT合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
3417 10
PPT合集|Flink Forward Asia 2024 上海站
|
21天前
|
人工智能 自然语言处理 前端开发
100个降噪蓝牙耳机免费领,用通义灵码从 0 开始打造一个完整APP
打开手机,录制下你完成的代码效果,发布到你的社交媒体,前 100 个@玺哥超Carry、@通义灵码的粉丝,可以免费获得一个降噪蓝牙耳机。
5927 16