c++学习笔记(七)—— 坑点/技巧总结和其他tips
2022/1/17 1:03:30
本文主要是介绍c++学习笔记(七)—— 坑点/技巧总结和其他tips,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
坑点/技巧总结
不要连续使用比较符
if (i < j < k) // 若k大于1则为真
建议使用++i
原因:i++需要将原始值保留下来,会造成浪费。如果是迭代器类型,这种操作消耗就很大了
运算对象可按任意顺序求值
i = fa(x) + fb(y); //fa和fb执行顺序不确定 *beg = toupper(*beg++); //错误:该赋值语句未定义
运算表达式中各项执行顺序不固定,上面第二个,编辑器有两种处理:
1、beg = toupper(beg); //先处理左边
2、(beg+1) = toupper(beg); //先处理右边
条件运算符优先级非常低
cout << grade < 60 ? 1 : 0; //错误: 试图比较cout和60
模板类定义和实现不能分开
C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。
悬垂else
无花括号的if-else,且if多于else时,else匹配最近的未被匹配的if
int a = 6; int b = 6; if (a > 5) if (b > 7) cout << "log1" << endl; else cout << "log2" << endl; // 最终输出log2
不要返回局部对象的引用或指针
因为函数结束后,局部变量就被释放掉了。
内存耗尽的new
内存耗尽时,new会抛出std::bad_alloc错误
但是我们可以改变new的使用方式来阻止
int *p1 = new (nothrow) int; //如果失败,返回一个空指针
赋值运算符
通常实现是:先深拷贝右侧的值到临时变量,然后销毁左侧的值,再调用左侧的拷贝构造。目的是为了防止两侧指向同一个地址,如果先销毁左侧的值,可能右侧会访问到野指针。
右值引用
为了防止在使用临时变量的过程中产生不必要的数据拷贝,引入了“对象移动”的概念。
简单理解就是移交一些临时变量的所有权,在程序中一些变量的生存期非常短,比如 部分表达式产生的值,后增运算符i++,函数返回值等等,而我们可以在他们即将销毁之前把他们的所有权“移动”(转移)给其他变量,它们在内存中的位置是不变的,也就是没有创建新的对对象,只不过归属于其他变量了,生存期也就随着所属的变量而变化了。
#include <iostream> #include <string> std::string foo() { return std::string("abc"); } int main() { std::string s3 = foo(); //这样的写法会调用拷贝构造函数 const std::string &s = foo(); //可以使用这个值,但是不能修改他 std::string &&s2 = foo(); //右值引用 }
完美转发
- std::forward()
- std::forward<>()
当用于一个指向模板参数类型的右值引用函数参数(T&&)时,forward会保持实参类型的所有细节
// 完美转发的翻转函数 template <typename F, typename T1, typename T2> void flip(F f, T1 &&t1, T2 &&t2) { f(forward<T2>(t2), forward<T1>(t1)); }
其他tips
- 大的类型变量避免拷贝,因为拷贝效率底,传参的时候,尽可能用引用
- IO对象不能拷贝和赋值(包括作为返回参数)
- forward_list增加和删除接口和其他容器不同,根本原因是无法访问前驱
- list和forward_list优先使用成员函数,而不是通用算法
- 如果我们用不到某个形参,那我们不需要为其命名
- 基类通常都应该定义一个虚析构函数,即使该函数不执行任何实际操作也是如此
- 如果一个函数参数是指向模板类型参数的右值引用(如T&&),它对应的实参的const属性和左右值属性将得到保持
- 调用析构函数或销毁对象,但是不会释放内存
这篇关于c++学习笔记(七)—— 坑点/技巧总结和其他tips的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享