首页 > 自考资讯 > 自考知识

c++程序改错题题库及答案解析大学生,c++程序改错

头条共创 2024-06-27

高效程序员必读技巧!

60051e4acc234960ba16905277eb3bae~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=Go145LZbIlsRMPRP8RBO1sW%2FZqc%3D(1)将C++视为语言联邦(C、面向对象C++、模板C++、STL)

(2) 预处理器可以用编译器代替(尝试用const、enum、inline代替#define)

(3) 尽可能使用const

(4)确保对象在使用前初始化(构造时赋值(复制构造函数)比构造后默认赋值(复制赋值)效率更高)

(5)了解C++中哪些函数是静默创建和调用的(编译器秘密地为类创建默认构造函数、复制构造函数、复制赋值运算符和析构函数)。

(6) 如果不想使用编译器自动生成的函数,则显式拒绝它(将不想使用的成员函数声明为私有,并且不实现它)

(7) 为多态基类声明一个虚析构函数(如果类有虚函数则需要一个虚析构函数)。

(8) 不要让异常从析构函数中逃逸(析构函数应该要么吞下异常而不传播异常,要么终止程序而不是抛出异常。如果要处理异常,请在非析构函数中处理。(必须是)正常功能)

(9) 永远不要在构造和销毁期间调用虚函数(因为这样的调用永远不会落入派生类中)

(10) 使Operator=返回对*this 的引用(用于链式赋值)

(11) 运算符=中“自赋值”的处理

(12)给对象赋值时,一定要复制“对象中的所有成员变量”和“所有基类组件”(调用基类的复制构造函数)。

(13)对象的资源管理(构造函数中获取资源,析构函数中释放资源。建议使用智能指针。获取资源的时间就是初始化的时间(资源获取初始化,RAII ))

(14)注意资源管理类中的复制操作(常见的RAII类复制操作包括复制抑制、引用计数、深复制、底层资源所有权转移(类似auto_ptr))

(15)在资源管理类中提供对原始资源的访问(对原始资源的访问可以显式或隐式转换;显式转换一般比较安全;隐式转换对客户来说更方便)。

43cb822e6f794e41959d3720684b1089~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=lpSkpLMxLMT%2FZhN4bipqGxqUqCM%3D (16) new 和delete 成对使用时,必须使用相同的格式(new 带[],然后delete [],new 不带[]),然后使用delete。

(17) 将新对象存储(放置)在另一个语句中的智能指针中(否则,编译器优化可能会导致隐藏资源泄漏)

(18)使接口易于正确使用且不易误用(促进正常使用的方法:接口的一致性、内置类型行为的兼容性、防止误用的方法:创建新类型、对类型的操作)限制、对象值约束),并消除客户对资源管理的责任)

(19)类设计与类型设计类似,需要考虑对象的创建、销毁、初始化、赋值、值传递、合法值、继承关系、转换、泛化等。

(20) 将pass-by-value 替换为pass-by-reference-to-const(前者通常更高效并且可以避免切片问题,但对于内置类型、STL 迭代器和函数对象不适用)。

(21) 如果必须返回一个对象,不要尝试返回对它的引用(返回对本地堆栈对象的指针或引用,返回对在堆上分配的对象的引用,或返回对本地堆栈的引用) (不返回指向的指针或引用)。静态对象(可能同时)需要多个这样的对象)。

(22)将成员变量声明为私有(为了封装、一致性、读写精确控制等)。

(23)将成员函数替换为非成员、非友元(可以提高封装性、封装灵活性、功能扩展性)

(24) 如果需要对所有参数(包括此指针指向的隐喻参数)进行类型转换,请使用非成员函数来实现此目的。

(25) 考虑创建一个不抛出异常的交换函数

(26)尽可能延迟变量定义的出现(可以增加程序清晰度,提高程序效率)

(27) 尝试尽可能少的转换(旧样式:(T)表达式、T(表达式);新样式:尝试const_castT(表达式)、dynamic_castT(表达式)、reinterpret_castT(表达式)、static_castT(表达式);避免转换和价值效率(我更喜欢避免dynamic_casts,尝试在没有转换的情况下进行设计,将转换封装在函数中,并使用新的转换)。

(28)避免使用句柄(包括引用、指针和迭代器)来指向对象(更好的封装,使const成员函数表现得像const,使用悬空指针等)以减少句柄的可能性)。

(29)“异常安全”是值得付出努力的(异常安全函数即使发生异常也不会泄漏资源或破坏数据结构;这些基本上是:它分为强列类型的三种可能的保证)、非抛出异常类型)

(30)彻底理解内联的细节(内联是大多数C++程序中的编译时行为,由编译器决定内联函数是否真正内联。它也拒绝复杂的(例如循环或递归) )通过内联函数,所有对虚函数的调用(除了最普通的函数)也无法内联。内联会使您的代码变得臃肿且效率降低。程序库升级不能升级内联函数。

27b392ff73ac4b4fbd8f78fac4e46ced~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=jPh5j1l%2BNe1WE0Ex%2B8EOZ1qGdRE%3D (31) 最小化文件之间的编译依赖关系(当可以使用对象引用或对象指针完成任务时,不要使用对象;如果可能,使用类定义(如果替换声明,定义将提供不同的定义)头文件。)

(32) 确保公共继承模型是-a关系(所有派生类对象也是基类对象,因此适用于基类的任何内容也适用于派生类)。

(33) 避免隐藏继承的名称(使用语句或转发函数将隐藏的名称公之于众)

(34)区分接口继承和实现继承(公有继承中,派生类总是继承基类的接口;纯虚函数只指定接口继承;非纯虚函数指定接口继承并指定默认实现继承(非纯虚函数)虚函数指定接口继承和默认实现继承)。虚函数指定接口继承和所需的实现继承)

(35)考虑虚函数以外的选项(例如模板方法设计模式的非虚接口(NVI)方法),将虚函数替换为“函数指针成员变量”,将虚函数替换为tr1:函数成员,并更改变量,继承系统。虚函数在继承系统中被另一个虚函数替换)

(36) 不要重新定义继承的非虚函数。

(37)虚函数是动态绑定的,而默认参数值是静态绑定的,所以不要重新定义继承的默认参数值。

(38) 通过复合模具has-a(拥有一个)或“根据”完成某事(在应用领域,复合意味着has-a(拥有一个),在实现领域,复合意味着被实施) -in-term-of(从某事物实现)。

(39) 明智且审慎地使用私有继承(私有继承意味着is-implemented-in-term-of;派生类基于受保护的基类。如果需要或需要访问类的成员,请尽可能使用组合)。如果您想重新定义继承的虚函数或需要空基优化,请使用私有继承)

(40) 明智而谨慎地使用多重继承(多重继承比单继承更复杂,并且可以引入新的歧义性以及虚拟继承的需要;虚拟继承可以解决多重继承中菱形继承的歧义问题,但是大小、增加成本,例如速度、初始化和分配复杂性。

(41)理解隐式接口和编译时多态性(类和模板都支持接口和多态性)。类的接口在其签名周围是显式的,并且多态性在运行时通过虚函数发生。模板接口是基于有效表达式的隐式接口。多态性在编译时通过模板实例化和函数重载决议发生)

(42)理解typename的双重含义(为模板声明类型参数时,前缀关键字class和typename具有完全相同的含义;关键字typename标识嵌套的从属类型名称)(但不在基类列表中) ; 或作为成员初始化列表中的基类修饰符)。

(43) 了解如何处理模板化基类中的名称(这是通过在派生类模板中通过this- 或显式编写的“基类修饰符”引用基类模板中的成员名称来完成的)这可以通过

(44)从模板中提取与参数无关的代码(使用非类型模板参数进行代码扩充)就是通过用类型参数(类型参数)来膨胀代码,从而用函数参数或类成员变量替换模板参数。用删除它。由于在具有相同二进制表示的实例化类型之间共享实现代码)

(45) 使用成员函数模板接受所有兼容类型(使用成员函数模板生成接受所有兼容类型的函数;您还必须为“广义复制构造”或“广义赋值操作”声明成员模板)。常规复制构造函数和复制赋值运算符)

09fc13929b78430ab1c818e67e2b8eee~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=A2sguUuJ2gIdQrocAutbaZvf4cY%3D (46) 如果需要类型转换,请为模板定义一个非成员函数(创建一个类模板并确保该模板提供的函数支持“隐式类型转换”,请定义它们)。这些函数充当“类模板中的友元函数”)

(47) 使用特征类来表达类型信息(特征类在编译时通过模板和模板特化使类型相关的信息可用,并通过重载技术(overloading)来实现if.else 测试)

(48) 了解模板元编程(TMP,Template Metaprogramming)允许您将工作从运行时转移到编译时,允许您使用TMP 来“基于策略选择的组合生成特定的自定义代码,也可用于避免生成代码”。这对于特定类型是不合适的)。

(49) 了解new-handler的工作原理(set_new_handler允许客户指定内存分配不满足时要调用的函数。nothrow new仅适用于内存分配(new运算符)(构造函数调用也可以抛出异常。)

(50)了解何时适当地替换new和delete(以检测应用程序错误,收集动态分配的内存使用统计信息,提高分配和恢复速度,并使用默认内存管理器来减少由于默认的非最佳对齐而导致的额外空间开销分配器,对相关对象进行聚类,并获取非传统行为)

b0868c4438d34fcd97bb0ea3164d18bd~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=1KHA5NZZ5p5afzCXufGORZL6saM%3D (51) 编写new和delete时必须遵循规则(operator new包含一个无限循环,必须尝试在其中分配内存。如果不可能,您应该调用new-handler来处理0字节请求,如下所示特定于类的版本还应该处理大于正确大小的请求。如果它收到空指针,则删除运算符不会处理“大于正确大小”的请求。

(52)使用new编写placement时,还必须为placement编写delete(使用new编写placement操作符时,一定要同时编写相应的placement操作符delete。否则,可能会出现微妙的、间歇性的内存泄漏。编写时展示位置声明、新的和删除的展示位置可能会无意中(无意)隐藏,请注意不要

(53) 不要忽略编译器警告

(54)熟悉标准库,包括TR1(TR1、C++ Technical Report 1、C++11标准草案文档)

(55)理解Boost(半标准库)

最重要的是

最后我写的是:如果你正准备学习C/C++编程,并希望进一步提高你的核心编程能力(内功),那么现在就开始吧。

分享编程学习书籍:

1b5170a7b968450d84be9ba4e8dd5617~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=tfZ4TS94FAuCg%2FyAl2awPZpJMfY%3D 编程学习视频分享:

9a4cdd1b33e34028beeeb0db856d3d8a~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720048662&x-signature=fRyTurpVGZ1xI3MgGqZAfeDbwAY%3D 整理分享(历年学习的源码、项目实践视频、项目笔记、基础入门教程)

我们欢迎想跳槽、学习编程的伙伴。通过比您想象的更多的信息来更快地学习和成长。

如果你对C/C++感兴趣,请关注小编后台私信我:【编程交流】一起学习免费的C/C++项目学习视频资料吧!设置了关键字自动回复,自动收集即可!

版权声明:本文由今日头条转载,如有侵犯您的版权,请联系本站编辑删除。

猜你喜欢