
Effective C++笔记
文章平均质量分 85
《Effective C++中文版》有多经典就不用说了,学习C++必备。
草上爬
专注技术,热爱分享
展开
-
Effective C++笔记之二十四:stack overflow
溢出(Stack Overflow)是指程序运行过程中,栈空间被耗尽,导致无法继续分配栈内存的错误。C++程序中,栈用于存储函数调用的局部变量、返回地址、函数参数等。当栈空间耗尽时,会引发栈溢出,通常导致程序崩溃。如果用的是Visual Studio,报错弹窗如下图所示。如果用的是其他IDE,比如所Qt Creator,直接crash了,无任何提示。通常的现象就是调用了一个函数,然后就崩了,注释调这个函数,一切正常。原创 2024-10-11 00:01:39 · 2321 阅读 · 0 评论 -
Effective C++笔记之二十三:非void函数不写return
Qt Creator查看汇编的步骤如下上图是g++编译器下的汇编eax就是main()函数的返回值如果删掉return 0;可以发现编译器还是把eax的值设为了0,由此可见,即使在main函数中不写return 0,编译器还是会默认添加个return 0。eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。原创 2024-09-17 12:27:04 · 2059 阅读 · 0 评论 -
Effective C++笔记之二十二:C++临时变量的析构
这行语句结束时这个变量就被析构了,指针c_str()指向的内存也被回收,所以下面使用的c_str()指向的内存已经被释放了,所以无法输出我的博客网址。预期输出:https://blog.youkuaiyun.com/caoshangpa,但实际上无论是VC++还是g++编译器下,输出都是乱码。但是把字符串改短点,比如改成“优快云”,VC++编译器下输出为空,但在g++编译器下,是能正常输出的。因此这个问题非常隐蔽,不仅与编译器相关,还和临时变量的具体内容相关,一旦发生,很难定位。根据上面的分析,这些都是存在问题的。原创 2024-09-15 08:50:43 · 1308 阅读 · 0 评论 -
Effective C++笔记之二十一:One Definition Rule(ODR)
其实这是C++普遍存在的问题,在.h里面定义了一个class或者template等东东,这个头文件被include到多个cpp里,在这些cpp里原样展开,编译器在链接的时候,就会看到多个重复的定义,于是C++规定了ODR(One Definition Rule),简而言之:"看到这种重复定义的类,且这些类的代码又长得一模一样,编译器就随便选一个用就行了"。结合前面的现象,在Release模式下,内联真正发生,函数在调用处展开,所以能得到正确结果,尽管如此,由于内联的非强制性,代码这样写依然是有隐患的。原创 2024-07-10 00:26:43 · 2430 阅读 · 3 评论 -
Effective C++笔记之二十:smart pointer的实现原理
Effective C++笔记之二十:smart pointer的实现原理。本文将简要介绍智能指针shared_ptr和unique_ptr,并简单实现基于引用计数的智能指针。原创 2018-01-31 20:05:16 · 7825 阅读 · 2 评论 -
Effective C++笔记之十九:static关键字
在全局变量前,加上关键字static,该变量就定义成为一个静态全局变量静态全局变量n和全局变量m和都存放于程序的全局数据区,它们的生存周期都是程序的整个运行期,但是m的作用域为全局作用域,可以通过extern在其他文件中使用,而n的作用域为文件作用域,只能在该文件中使用。即:在声明全局的static变量时,static没有改变它的生存周期,也即存储位置(因为全局变量本来就存储在全局数据域),而是将变量的作用域限制在当前文件中。原创 2017-11-11 11:03:11 · 2248 阅读 · 1 评论 -
Effective C++笔记之十八:C++中的explicit关键字
C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)。但是, 也有一个例外, 就是当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数。那么CExample objFour = 12;这条语句将不能通过编译。原创 2017-12-07 16:00:58 · 2264 阅读 · 0 评论 -
Effective C++笔记之十七:善用PIMPL技巧
Effective C++笔记之十七:善用PIMPL技巧PIMPL(Pointer to Implementation)这个手法可以解決/改善C++编码时常碰到的2大问题。1.class增加private/protected成员时,使用此class的相关 .cpp(s) 需要重新编译。2.定义冲突与跨平台编译原创 2017-11-21 11:46:17 · 10881 阅读 · 4 评论 -
Effective C++笔记之十六:C++中使用placement new
一.newnew operator就是new操作符,不能被重载,假如A是一个类,那么A * a=new A;实际上执行如下3个过程。(1)调用operator new分配内存,operator new (sizeof(A))(2)调用构造函数生成类对象,A::A()(3)返回相应指针事实上,分配内存这一操作就是由operator new(size_t)来完成的,如果类A重载了o原创 2017-12-22 20:10:12 · 4395 阅读 · 2 评论 -
Effective C++笔记之十五:inline函数的里里外外
1.inline函数简介inline函数是由inline关键字来定义,引入inline函数的主要原因是用它替代C中复杂易错不易维护的宏函数。2.编译器对inline函数的处理办法inline对于编译器而言,在编译阶段完成对inline函数的处理。将调用动作替换为函数的本体。但是它只是一种建议,编译器可以去做,也可以不去做。从逻辑上来说,编译器对inline函数的处理步骤一般如下:(1)将inli...原创 2018-05-18 18:40:38 · 2199 阅读 · 1 评论 -
Effective C++笔记之十四:以pass-by-reference-to-const替换pass-by-value
缺省情况下C++ 以by value方式(一个继承自C 的方式)传递对象至(或来自)函数。函数参数都是以实际实参的复件(副本)为初值。这些复件(副本)系由对象的copy构造函数产出,这可能使得pass-by-value成为昂贵的(费时的)操作。考虑以下class 继承体系:class Person { public: Person (); virtual ...原创 2018-05-18 17:25:23 · 2155 阅读 · 0 评论 -
Effective C++笔记之十三:以独立语句将newed对象置入智能指针
假设我们有个函数用来揭示处理程序的优先权,另一个函数用来在某动态分配所得的Widget 上进行某些带有优先权的处理:int priority () ; void processWidget(std::trl::shared_ptr<Widget> pw, int priority); 考虑如下调用:processWidget(std::trl::sha...原创 2018-05-18 17:04:43 · 2091 阅读 · 1 评论 -
Effective C++笔记之十二:成对使用new和delete时要采取相同形式
以下动作有什么错?std::string* stringArray = new std::string[100]; ...... delete stringArray; 每件事看起来都井然有序。使用了new,也搭配了对应的delete。但还是有某样东西完全错误:你的程序行为不明确(未有定义)。最低限度,stringArray所含的100 个string 对象中...原创 2018-05-18 16:31:05 · 2074 阅读 · 0 评论 -
Effective C++笔记之十一:复制对象时勿忘其每一个成分
设计良好之面向对象系统(OO-systems )会将对象的内部封装起来,只留两个函数负责对象拷贝(复制),那便是带着适切名称的copy构造函数和copy assignment操作符,我称它们为copying 函数。编译器会在必要时候为我们的classes创建copying 函数,并说明这些"编译器生成版"的行为: 将被拷对象的所有成员变量都做一份拷贝。 如果你声明自己的c...原创 2018-05-18 16:10:22 · 2071 阅读 · 0 评论 -
Effective C++笔记之十:令operator= 返回一个reference to *this
关于赋值,有趣的是你可以把它们写成连锁形式:int x, y, z;x = y = z = 15; // 赋值连锁形式 同样有趣的是,赋值采用右结合律,所以上述连锁赋值被解析为:x = (y = (z = 15)); 这里15 先被赋值给z,然后其结果(更新后的z) 再被赋值给y,然后其结果(更新后的y) 再被赋值给x 。 为了实现"连锁赋值",赋...原创 2018-05-18 15:26:43 · 2046 阅读 · 0 评论 -
Effective C++笔记之九:绝不在构造和析构过程中调virtual函数
本条款开始前我要先阐述重点2:你不该在构造函数和析构函数期间调用virtual函数,因为这样的调用不会带来你预想的结果,就算有你也不会高兴。如果你同时也是一位Java 或C# 程序员,请更加注意本条款,因为这是C++ 与它们不相同的一个地方。 假设你有个class 继承体系,用来塑模股市交易如买进、卖出的订单等等。这样的交易一定要经过审计,所以每当创建个个交易对象,在审计...原创 2018-05-18 15:17:59 · 2109 阅读 · 0 评论 -
Effective C++笔记之八:template中的class、typename关键字
template 声明式中,class 和 typename 这两个关键字意义完全相同template class Widget;template class Widget;有时候你一定要用 typename。template void print2nd(const C& container) { if (container.size() >= 2) {原创 2018-04-24 20:21:38 · 2865 阅读 · 0 评论 -
Effective C++笔记之七:为多态基类声明virtual析构函数
就像本文标题所说的那样,应该为多态基类声明virtual析构函数,否则容易造成内存泄露。 因为C++明白指出,当derived class对象经由一个base class指针被删除,而该base class如果带有一个non-virtual析构函数,其结果未定义一实际执行时通常发生的是对象的derived成分没被销毁。举个例子:#includeusing namespace std;cla原创 2018-03-13 09:29:14 · 2029 阅读 · 0 评论 -
Effective C++笔记之六:使用noncopyable禁止类的拷贝
如果某些事物是独一无二的,那么其相应的类就应该禁止拷贝,也就是要使类的copy构造函数和copy assignment操作符不起作用。比如说,地球就是独一无二的,那么可以这么定义地球:class Earth {public: ......//member函数或friend函数private: Earth(const Earth&);//只声明 Earth&am...原创 2018-03-09 09:54:03 · 2667 阅读 · 0 评论 -
Effective C++笔记之五:了解C++默默编写并调用哪些函数
什么时候empty class(空类)不再是个empty class呢?当C++处理过它之后。是的,如果你自己没声明,编译器就会为它声明(编译器版本的)一个copy 构造函数、一个copy assignment操作符和一个析构函数。此外如果你没有声明任何构造函数,编译器也会为你声明一个default构造函数。所有这些函数都是public且inline。因此,如果你写下:class E...原创 2018-03-07 13:43:39 · 2016 阅读 · 0 评论 -
Effective C++笔记之四:确定对象被使用前已先被初始化
关于初始化的定义参考Effective C++笔记之一:声明、定义、初始化与赋值,这里先看一个例子:#include <iostream>using namespace std;class TestA{public: TestA() { cout << "default constructor" << endl; } ...原创 2018-03-04 22:37:16 · 2048 阅读 · 0 评论 -
Effective C++笔记之三:尽可能使用const
关键字const多才多艺。你可以用它在classes外部修饰global或namespace(见Effective C++笔记之二) 作用域中的常量,或修饰文件、函数、或区块作用域(block scope)中被声明为static的对象。你也可以用它修饰classes内部的static和non-static成员变量。面对指针,你也可以指出指针自身、指针所指物,或两者都(或都不)是con...原创 2018-03-04 15:30:45 · 2601 阅读 · 0 评论 -
Effective C++笔记之二:尽量以const、enum、inline替换#define
一.#define定义的类似函数的宏,使用时易出错缺点描述这样做的初衷是,宏看起来像函数,但不会招致函数调用(function call)带来的额外开销。但即使你为所有实参加上小括,仍然会在使用时遭遇麻烦。举个例子:// 求两个变量中最大的那个#define THE_MAX(a, b) f((a) > (b) ? (a) : (b))当这样使用的时候:THE_MAX(++a, ++b);a...原创 2018-03-03 21:37:32 · 2277 阅读 · 0 评论 -
Effective C++笔记之一:声明、定义、初始化与赋值
一.声明(Declaration) 声明的作用是指定变量的类型和名称,makes a name known to the program。区分声明和定义可以让C++支持分开编译,比如A.cpp中定义了变量var1,在B.cpp中只需要声明var1这个变量就可以直接使用。因为这样的用法,声明常常见于头文件中。源文件包含头文件之后,就可以使用这个变量,即使没有看到该变量的定义。 声明的语法...原创 2018-03-03 16:27:05 · 2687 阅读 · 0 评论