C++
文章平均质量分 66
啊大1号
三百六十行,行行敲代码
展开
-
C/C++中的序列点
Table of Contents转载说明: 0. 什么是副作用(side effects) 1. 什么是序列点(sequence points) 2. 表达式求值(evaluation of expressions)与副作用发生的相互顺序 3. 序列点对副作用的限制 4. 编译器的跨序列点优化 5. C99定义的序列点列表 6. C++2003定义的序列点列表 7. C++2...转载 2018-07-17 12:51:17 · 1558 阅读 · 0 评论 -
C++ 虚函数表解析---陈皓改进版
修正了一些原文中的错误。前言C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术(Run-Time Type Identification),虚函数技术,要...转载 2018-08-29 22:36:35 · 3606 阅读 · 7 评论 -
C++ 对象的内存布局(下)---陈皓改进版
修正了一些原文中的错误。续接:C++ 对象的内存布局(上)---陈皓改进版重复继承下面我们再来看看,发生重复继承的情况。所谓重复继承,也就是某个基类被间接地重复继承了多次。下图是一个继承图,我们重载了父类的f()函数。 其类继承的源代码如下所示。其中,每个类都有两个变量,一个是整形(4字节),一个是字符(1字节),而且还有自己的虚函数,自己overwrite父类的虚函数。...转载 2018-09-01 17:46:02 · 1975 阅读 · 6 评论 -
C++智能指针的简单剖析
导读最近在补看《C++ Primer Plus》第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑。看开源的C++项目时,也能随处看到智能指针的影子。下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰。目录智能指针背后的设计思想 C++智能指针简单介绍 为什么摒弃auto_ptr? unique_ptr为何优于auto_ptr...转载 2018-09-11 22:32:13 · 273 阅读 · 0 评论 -
C++11 lambda表达式不能捕获map/unordered_map值
先看一道面试题。某公司中有N名员工,给定所有员工工资的清单,财务人员要按照持定的顺序排列员工的工资,他按照工资的频次降序排列,即给定清单中所有频次较高的工资将在频次较低的工资之前出现,如果相同数量的员工都有相同的工资,则将按照给定清单中该工资第一次出现的顺序排列。写一算法来帮助财务人员排列员工工资的顺序。输入:该函数/方法的输入包括两个参数——num,一个整数,表示员工的人数。s...原创 2018-09-15 22:58:39 · 1726 阅读 · 0 评论 -
什么是类型安全? (C和C++类型安全比较)
什么是类型安全?类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图访问自己没被授权的内存区域。“类型安全”常被用来形容编程语言,其根据在于该门编程语言是否提供保障类型安全的机制;有的时候也用“类型安全”形容某个程序,判别的标准在于该程序是否隐含类型错误。类型安全的编程语言与类型安全的程序之间,没有必然联系。好的程序员可以使用类型不那么安全的语言写出类型相当安全的程序,相反的,差一点儿的...转载 2018-09-07 16:52:00 · 18826 阅读 · 1 评论 -
c++ iterator(迭代器)分类及其使用
总所周知,c++的stl中提出了iterator的概念,这是C所没有的.在一般的使用中,iterator的行为很像c内建的指针.而在java和c#中索性就直接取消了指针,而采用类似iterator的做法来代替了指针.很多编程人员在使用iterator的时候也仅仅把他当作了指针的一个变体而没有多加注意。 不过既然是学习,那我们在使用的时候也要知道其存在的原因,其分类以及用法吧. 首先...转载 2018-10-03 20:54:30 · 3194 阅读 · 0 评论 -
C/C++ 循环内还是循环外定义变量更好?
问:// 方法 A:Widget w;for (int i = 0; i < n; ++i) { w = 取决于 i 的某个值;}// 方法 B:for (int i = 0; i < n; ++i) { Widget w(取决于 i 的某个值);}Effective C++ 条款 26 有一段话大概是:当一个赋值成本低于一组构造+析构成本,定义...转载 2018-10-04 16:35:22 · 4929 阅读 · 0 评论 -
C++11之前和C++11之后的 vector 构造函数的区别
例子:#include <iostream>#include <vector>using namespace std;class A{public: A(const char* s = "1234") { cout << "ASDF" << endl; }};int main(){ vector<A&am原创 2018-10-06 00:22:51 · 3327 阅读 · 0 评论 -
C++ STL中Map的按Key排序和按Value排序
map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value。假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择。 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key;该学生的成绩用int类型,作为value。这样一来,我们可以根据学生姓名...转载 2018-10-13 00:03:10 · 718 阅读 · 0 评论 -
C++ 引用作为函数返回值
(1)以引用返回函数值,定义函数时需要在函数名前加 &(2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。引用作为返回值,必须遵守以下规则:(1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。#include <iostream>using namespace s...原创 2018-10-23 13:35:59 · 28324 阅读 · 14 评论 -
剑指offer纪念版 何海涛著 部分纠正
类似的再举一个例子:题目:从上往下打印二叉树,何老师的代码如下(是没有问题的):void PrintFromTopToBottom(BinaryTreeNode* pRoot){ if(pRoot == nullptr) return; std::deque<BinaryTreeNode *> dequeTreeNode; ...原创 2018-10-23 16:33:55 · 673 阅读 · 0 评论 -
C++ 重载、重写(覆盖)、重定义(隐藏) 与 Java 重载、重写(覆盖)、隐藏的区别
C++:一、重载(overload)指函数名相同,但是它的参数表列个数或顺序,类型不同。但是不能靠返回类型来判断。(1)相同的范围(在同一个作用域中) ;(2)函数名字相同;(3)参数不同;(4)virtual 关键字可有可无。(5)返回值可以不同;二、重写(也称为覆盖 override)是指派生类重新定义基类的虚函数,特征是:(1)不在同一个作用域(分别位于派生类与基类) ;...原创 2018-11-18 17:21:09 · 483 阅读 · 3 评论 -
为什么 C++ 有指针了还要引用?
今天师弟问我,引用的底层也是指针实现的,内置类型指针传递和引用传递的汇编代码是一样的,那C++为什么还需要引入引用呢?好吧,仔细想了下,这确实是个好问题。引用传递,只是明面上,没有使用值传递,值传递本身是不可避免的。编译器,暗地里通过指针(或者其他可以替代指针的数据类型)的值传递,替换了引用传递。所以引用传递,实质上是地址传递,别名这东西只是概念,是一种抽象,别名是没法传递的。别名,可不...原创 2018-11-29 11:32:04 · 12293 阅读 · 4 评论 -
为什么用feof()或者iostream::eof来控制循环是不好的
例1:data.txt为:data.txt十六进制如下:可看出结尾有一个换行符(注:Windows下换行符为\r\n)。#include <stdio.h>int main(){ FILE *fp; int i = 0; char s[3][7]; if ((fp = fopen("data.txt", "r")) == NULL) pri...原创 2019-06-26 20:51:24 · 431 阅读 · 0 评论 -
C++ public、protected 、 private和friend(最通俗易懂)
C++ 继承面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物...原创 2018-08-29 20:35:44 · 17321 阅读 · 2 评论 -
sizeof与strlen的区别和#pragma pack的具体含义(非常详细)
char str[20]="0123456789"; int a=strlen(str); // a=10;strlen 计算字符串的长度,以'\0'为字符串结束标记,长度不包括'\0'。 int b=sizeof(str); // b=20;sizeof 计算的则是分配的数组str[20] 所占的内存空间的大小,不受里面存储的内容影响。 #pragma pack的具体含义...原创 2018-08-29 14:22:16 · 440 阅读 · 0 评论 -
C/C++ strlen函数为什么不能传入空指针NULL?
#include <iostream>using namespace std;int main(){ int a; char *name = NULL; a = strlen(name); return 0;}以上程序编译没问题,运行将会报错。原因就是name为NULL,strlen参数不能为NULL,为探究原因,我查看了glibc对strlen函数的实现代码如下...原创 2018-07-05 21:43:45 · 9173 阅读 · 0 评论 -
STL容器之vector 的下标越界是否报错
今天将程序在VS2015和g++ 5.4.0下运行,发现vector越界 VS会报错,而g++正常输出。故而查看了源码,看个究竟。例:#include <iostream>#include <vector>using namespace std;int main(){ vector <int> a; a.push_back(6...原创 2018-07-13 22:45:05 · 5725 阅读 · 0 评论 -
cin、cin.get()、cin.getline()、getline()的区别
测试平台g++ 5.4.0和VS2015社区版。输入原理简述:程序的输入都建有一个缓冲区,即输入缓冲区。每次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。比如下面的例子:voidtest_i...原创 2018-05-14 15:51:30 · 87960 阅读 · 43 评论 -
C++构造函数详解及显式调用构造函数(explicit)
一. 什么是拷贝构造函数首先对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。#include <iostream> using namespace std; class CExample {...转载 2018-06-01 19:57:35 · 21378 阅读 · 1 评论 -
C++常量表达式、const、constexpr(C++11新增)的区别
常量表达式是指值不会改变且在编译过程中就能够得到计算结果的表达式,能在编译时求值的表达式。例1:#include <iostream>using namespace std;int main(){ const int a1 = 10; // a1是常量表达式。 const int a2 = a1 + 20; // a2是常量表达...原创 2018-08-05 14:01:03 · 2991 阅读 · 2 评论 -
C++ 内存分配(new,operator new)详解
本文主要讲述C++ new关键字和operator new, placement new之间的种种关联,new的底层实现,以及operator new的重载和一些在内存池,STL中的应用。一. new operator 和 operator newnew operator:指我们在C++里通常用到的关键字,比如A* a = new A; operator new:它是一个操作符,并且可被...转载 2018-05-06 12:19:31 · 553 阅读 · 0 评论 -
std::exception标准和各平台实现的不同
C++98标准:C++11标准:g++ 5.4.0实现如下:VS2015实现如下:可见,g++只是实现了标准中的默认构造函数;而VS扩展了标准,新增了explicit exception(char const* const _Message) throw()和exception(char const* const _Message, int) throw();即像t...原创 2018-08-01 14:25:26 · 1328 阅读 · 0 评论 -
C++的匿名对象
今天在github看到有人抛出如下异常:throw std::exception("Invalid input."); 即抛出了一个匿名对象。就比较了一下c++标准和各平台的实现:https://blog.csdn.net/a3192048/article/details/81329976顺便也整理下c++的匿名对象。C++中的匿名对象是pure RValue, 因而不能作为引用传进去...原创 2018-08-01 21:35:05 · 7770 阅读 · 0 评论 -
八大排序算法原理及实现
概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。我们这里说说八大排序就是内部排序。 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布...转载 2018-05-10 16:29:07 · 73099 阅读 · 10 评论 -
C++中class和typename的区别
由于历史原因,以前是用class,后来C++ Standard 出现后,引入了typename, 所以他们基本上是一样的,但也有区别。例1:// 定义一个返回参数中较大者的通用函数template <typename T>const T& max(const T& x, const T& y){ return x > y ? x : y...原创 2018-08-02 18:57:35 · 1019 阅读 · 1 评论 -
不同编译器虚函数的实现方式的区别
class base { virtual void f1() {}};base bs;问:“为什么bs虚函数表的地址(int*)(&bs)与虚函数f1()地址(int*)*(int*)(&bs) 不是同一个?”注:题主理解错了,其实(int*)(&bs)是对象bs的地址,即虚函数表的地址的地址。(int*)*(int*)(&bs)才是虚函数表地址...转载 2018-08-31 12:56:47 · 818 阅读 · 0 评论 -
VS工程属性“字符集”和源文件“高级保存选项”字符集区别
项目--属性--设置属性--常规--字符集,VS2015默认为Unicode字符集。一、工程字符集属性工程属性里,字符集可以选择“使用Unicode字符集”和“使用多字节字符集”。此选项只控制代码里的API是用宽字符版(即Unicode)的还是ANSI字符版(即GBK)的,它控制不了代码里的字符是用Unicode编码还是ANSI编码。如果选择了“使用Unicode字符集”,则...原创 2018-08-28 22:17:57 · 3327 阅读 · 0 评论 -
C++ 对象的内存布局(上)---陈皓改进版
前言查看本文之前最好先看这篇文章:C++ 虚函数表解析---陈皓改进版07年12月,我写了一篇《C++ 虚函数表解析》的文章,引起了大家的兴趣。有很多朋友对我的文章留了言,有鼓励我的,有批评我的,还有很多问问题的。我在这里一并对大家的留言表示感谢。这也是我为什么再写一篇续言的原因。因为,在上一篇文章中,我用了的示例都是非常简单的,主要是为了说明一些机理上的问题,也是为了图一些表达上方便...转载 2018-08-31 20:40:50 · 2226 阅读 · 0 评论 -
c++对象创建带括号与无括号的区别
class Test{public: Test() {} Test(int a) {}}1、栈上创建对象 1.1 无括号 Test a; // 调用默认构造函数,栈上分配内存创建对象 1.2 有括号 Test a(); // 无任何意义,声明一个返回值为Test对象的无参函数 1.3 有括号+参数 Test a(2); // 调用构造函数...原创 2019-08-30 00:47:08 · 676 阅读 · 0 评论