C&C++结构体内存对齐
结构体内存对齐先来看这几个结构体,并计算它们的大小
123456789101112131415161718struct A // 8{ char a; int b;};struct B // 16{ char c; int d; double e;};struct C // 24{ char f; int g; double h; char i;};
输出的结果并非是实际成员占用的字节数,这就是结构体内存对齐。
结构体内存对齐的原因
1.平台原因(移植原因)
不是所有硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些特定地址处取某些特定的数据,否则就会抛出硬件异常。也就是说计算机在读取内存数据时,只能在规定的地址处读数据,而不是在内存中任意位置都会可以读取的。
2.效率原因
正是由于只能在特定的地址处读取数据,所以在访问一些数据时,对于访问未对齐的内存,处理器需要进行两次访问;而对于对齐的内存,只需要访问一次就可以,其实这是一种以空间换时间的做法,并且这种做法是值得的。
结构体内存对齐规则
第一个成员在结构体 ...
C++智能指针
C++智能指针为什么要使用智能指针?<<C++ Primer>> p400
虽然使用动态内存有时是必要的,但众所周知,正确地管理动态内存是非常棘手的。
为了更容易(同时也更安全的)地使用动态内存,新的标准库提供了两种智能指针,来管理动态对象。智能指针的行为类似于常规指针,重要的区别是它负责自动释放所指向的对象。
shared_ptr允许多个指针指向同一个对象,unique_ptr是“独占”所指向的对象。标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memeory头文件中。
原理:将我们分配的动态内存都交给有生命周期的对象来处理,当对象过期时,让它的析构函数删除指向的内存。
C++98 提供了 auto_ptr模板的解决方案
C++11 增加了 unique_ptr、shared_ptr、weak_ptr
(就是一个类模板,里面有析构函数,能够自动释放这个对象开辟的内存。)
auto_ptrC++98的智能指针模板,其定义了管理指针的对象,可以将new获得(直接或间接获得)的地址赋值给这 ...
C++explicit关键字、类型转换、左右值
C++补充知识&C++11及其特性
explicit关键字加在类构造函数前表明该构造函数是显式的,并非隐式的,不能进行隐式类型转换!
类构造函数默认情况下声明为隐式。
给构造函数加上关键字explicit使得该类创建对象必须显式调用构造。
12345student xiaohua(18);//显式构造student xiaoming = 18;//隐式构造student xiaoli("小李",18);//显式构造student xiaomei = ("小美",18);//隐式构造-C++11之前编译不能过//初始化参数列表C++11新增
看到=要想是赋值呢,还是隐式构造呢。
左值和右值的概念
按字面意思,通俗的说,以赋值运算符=为界,左边的就是左值,右边的就是右值。
左值(lvalue)——代表一个在内存中占有确定位置的对象(就是有一个地址)。
右值(rvalue)——通过排他性来定义,每个表达式不是左值就是右值,rvalue是不在内存中占有确定位置的表达式,而是在存在寄存器中。
所有的左值(无论是数组,函数或不完全类型)都可以转化 ...
C++使用内置容器实现自定义容器
MySet容器实现MySet .hpp
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140#ifndef _myset#define _myset#include<iostream>#include<set>using namespace std;//基于set容器来实现MySet自定义容器//参数1为 里面存的数据类型 参数2 用哪种容器来实现,并且默认为set容器/** 注: 在模板(t ...
C++STL容器知识点小结
STL标准模板库
STL主要分为分为三类:
algorithm(算法) - 对数据进行处理(解决问题) 步骤的有限集合
container(容器) - 用来管理一组数据元素
Iterator (迭代器) - 可遍历STL容器内全部或部分元素”的对象
容器和算法通过迭代器可以进行无缝地连接。在STL中几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
STL 最早源于惠普实验室,早于C++存在,但是C++引入STL概念后,STL就成为C++的一部分,因为它被内建在你的编译器之内,不需要另行安装。
STL被组织为下面的13个头文件:
< algorithm >
< memory >
< deque >
< numeric >
< functional >
< queue >
< iterator >
< set >
< vector >
< stack >
< list ...
C++仿函数(函数对象)
仿函数(函数对象)研究set/multiset容器的排序原理。
当我们构造一个存放int类型的set容器时
1set<int> s1;
系统会自动帮我们设定并调用一个函数,自动调用头文件functional中的仿函数(一个类中重载了()实现了对比的操作,从而完成了排序)。
1set<int,less<int>> s1;
less函数对象实现比较,为排序提供依据。(升序)greater(降序)
functional中,如图
手动实现:
123456789101112131415161718192021222324252627282930313233343536373839404142#include<iostream>#include<set>using namespace std;class Student{public: Student(int _age):age(_age) { } int getAge()const { return age; } bool ope ...
C++:explicit关键字、左右值、类型转换
C++11新特性:变参模板、完美转发和emplace使得 emplace 可以接受任意参数,这样就可以适用于任意对象的构建。
《C++Primer》:新标准引入了三个是新成员——emplace、emplace_front和emplace_back,这些操作构造而不是拷贝元素。这些操作分别对应着,insert、push_front、push_back,允许我们将元素放置在容器头部、一个指定位置之前或容器尾部。
当我们调用push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造元素。
问题代码如下:
123456789101112131415161718192021222324252627282930313233343536373839#include<iostream>#include<vector>#include<string>#include<list>usin ...
C++异常处理知识点总结
Exception handling mechanism
就是它要这个类型数值,你给它一个不合格的,反馈给你看错误提示。
异常是一种程序控制机制,与函数机制互补。
函数是一种以栈结构展开的上下函数衔接的程序控制系统。
异常是另一种控制结构,它可以在出现“意外”时中断当前函数,并以某种机制(类型匹配)回馈给隔代的调用者相关的信息。
C++ Primer中关于异常的解释:(p172)
异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。
典型的异常包括失去数据库链接以及遇到意外输入等。
处理反常行为可能是纯设计所有系统中最难的一部分。
通过返回值实现异常处理机制12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970#include <stdio.h>#include <stdlib.h>#define BUFSIZE 1024//实现文件的 ...
C++模板知识点总结
Templatefunction template函数模板就是建立一个通用的函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。
template< typename T >(class和typename都行)
1234参数类型自动推导 Max(x,y);显示类型调用 Max<int>(x,y);
template function
调用函数模板,编译器私底下会 根据传过来的变量创建对应的函数,将它具体化。——这就是通过编译生成的模板函数。
小结:
我们注意到,函数模板和函数重载似乎很类似,当他们两个并存时,如果参数类型和普通函数更匹配,就调用普通函数。
不存在普通函数,函数模板会隐式类型转换吗?不会。不提供隐式的类型转换,必须是严格的匹配。
如果显式的调用函数模板,则使用<>类型列表。
如果函数模板会产生更好的匹配,使用函数模板。
当所传参数需要隐式类型转换时,优先调用普通函数。
函数模板也可以重载。
编译器并不是把函数模板处理成能够处理任意类型的函数。
编译器从函数模板通过具体的参数类型产 ...
C++基础知识复习
namespace_命名空间C++避免名字冲突——使用命名空间。
例如:不同命名空间中的同一个变量,所对应的内容不同。
1234567891011121314151617#include<iostream>namespace China { double population = 14.1; std::string capital = "北京";}namespace XiaoRiben { double population = 1.27; std::string capital = "东京";}int main(void){ std::cout << China::capital << std::endl; std::cout << XiaoRiben::capital << std::endl; return 0;}
cout是标准命名空间std已经定义好的。
或者用using ...
C++虚函数知识点总结
虚函数注意:
在函数声明的返回类型之前加virtual。
并且只在函数的声明中添加virtual,在该成员函数的实现中不用加。
虚函数的继承
如果某个成员函数被声明成虚函数,那么他的子类,以及子类中的子类 ,所计继承的这个成员函数,也自动是虚函数。
如果在子类中重写这个虚函数,可以不用再加virtual,但仍然建议加上virtual,提高代码的可读性。
虚函数原理——虚函数表对应虚函数的类,该类的对象所占内存大小为,数据成员的大小+一个指向虚函数表指针 (4字节)。
例如:如下所示Father类所创建的对象
12345678910111213141516171819202122232425class Father{public: virtual void func1() { cout << "虚函数func1" << endl; } virtual void func2() { cout << "虚函数func2" << endl; ...
位图算法
位图算法已空间换时间。
很多不重复的整数,其中最大值不超过40亿,最小值是0,要求判断某个指定的整数,是否在这个集合中。
使用2个字节,表示16个数,的状态(有或者没有)
上面为表示的数,下面为该数的个数。
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
例如:要表示1,13,4,5,6
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0
0
1
0
0
0
0
0
0
1
1
1
0
0
1
0
要表示40亿个数
4000000000/8 = 500000000字节
500000000字节/1024= 488281K
488281k/1024 = 476.837M
单位换算
1字节== 8比特位
1K == 1024字节
1M == 1024K
代码实现:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 ...
侯捷C++面向对象高级编程(上)笔记
前言面向对象,就是将数据和处理这些数据的函数包在一起。数据只有这个函数能够看到,不会和其他的混杂在一起。
1c++ class -> c struct + 更多的特性
C++的结构几乎等同于class。
C++ Programs代码基本形式文件类型12.h(header files).cpp
延伸文件名(extension file name)不一定是.h Or .cpp,也可能是.hpp或者其他甚至无扩展名。
头文件写法防止头文件重复包含
12#ifndef _XXX#define _XXX_
头文件布局123前置声明类——声明类——定义-功能实现
class1——complex类的声明
inline——内联函数增加了 inline 关键字的函数称为“内联函数”。内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样。(链接)
inline是C++关键字,在函数声明或定义中,函数返回类型前加上关键字inline,即可以把函数指定为内联函数。这 ...
【网络编程】异步选择模型
异步选择模型逻辑核心:消息队列,操作系统为每个窗口创建一个消息队列,并且维护,我们想要使用消息队列,那就要创建一个窗口。
第一步:将我们的socket,绑定在一个消息上,并且投递给操作系统。
WSAAsyncSelect
第二步:取消息分类处理,
该模型只能用于windows,windows处理用户操作的核心就是消息队列。但是思想是通用的。
窗口第一步:创建窗口结构体——WNDCLASSEX
第二步:注册窗口结构体——RegisterClassEx
第三步:创建窗口——CreateWindowEx
第四步:显示窗口——ShowWindow
第五步:消息循环——GetMessage
——TranslateMessage
——DispatchMessage
第六步:回调函数
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555 ...
【网络编程】事件选择模型
事件选择模型windows处理用户行为的两种方式消息机制核心:消息队列
处理过程:所有的用户操作,比如点鼠标,按键盘,对软件进行的各种操作……等等,所有操作均依次按顺序被记录,装进一个队列。不同的操作对应着不同的编号。
特点:消息队列由操作系统维护,用户进行操作,然后把消息读取出来,分类处理。有先后顺序。动态的。
异步选择模型就是基于这个消息的。
事件机制核心:事件集合
处理过程:根据需求我们为用户的特定操作绑定一个事件,事件由我们自己调用API创建,需要多少创建多少。
将时间投递给系统,系统就帮我们监视着,所以不能无限创建,太多了系统运行就卡了。
如果操作发生了,比如用户按鼠标了,那么对应的事件就会被置成有信号,也就是类似1变2,用个数来标记。
直接获取到有信号的时间进行处理。
特点:所有时间都是咱们自己定义的,系统只是帮咱们标记有无信号。无序。
事件选择模型,就是应用这个。
事件选择整体类似于select
创建一个事件对象(变量),WSACreateEvent
为每一个事件对象绑定socket以及操作accept,read,close…..
投递给系统让其监管,WSAEven ...
【网络编程】select模型
select模型特点
解决基本c/s模型中,accept,rcev傻等的问题。
傻等阻塞
执行阻塞 send recv accept 在执行的复制粘贴的过程中都是阻塞的。
(网络模型就是解决阻塞问题的)
实现多个客户端链接,与多个客户端分别通信。
用于服务器,因为客户端就一个socket。
服务器端12345678网络头文件 网络库打开网络库校验版本创建socket绑定地址与端口开始监听 select
逻辑
每个客户端都有socket,服务器也有自己的socket,将所有的socket装进一个数据结构里,即数组。
通过select函数,遍历1中的socket数组,当某个socket有相应,select就会通过其参数/返回值反馈出来。
处理。如果见得到的是服务器socket,那就有客户端链接,调用accept。如果检测到客户端socket,那就是客户端请求通信,调用send或者recv。
定义一个装客户端的socket结构体fd_set是网络库中定义好的类型。
123456789101112typedef struct fd_set { //几个 ...
【网络编程】基于TCP/IP协议的C/S模型
相关视频——C3程序猿-windows网络编程:第一部分tcp/ip
基于TCP/IP协议的C/S模型TCP/IP协议全称——Transmission Control Protocol / Internet Protocol
重要性——TCP/IP协议是今天互联网的基石,没有这个就上不了网
概念——TCP/IP协议族(簇,组,体系),并不是TCP协议和IP协议的总称,指的是整个网络传输体系。而TCP协议和IP协议就是单单的两个协议。
特点——面向可连接的,可靠的,基于数据报的传输协议层。
UDP/IP协议——面向非连接的,不可靠的,基于数据报的传输层协议。
Client/Server客户端/服务器模型C/S模型其实是概念层面的,实现层面可以是基于任何的网络协议。
常见的还有B/S模型——浏览器/服务器模型,基于http/https协议的
套接字编程与socket编程socket中文——套接字
统称网络编程
使用
局域网
广域网——内网穿透,内网转发
服务端网络头文件&网络库是最底层的网络函数,QT、MFC、WPF等封装好的网络库都是对这些最本质的网络函数的二次封装。
不区 ...
LeetCode刷题(14)【简单】加一(C++)
加一题目链接——加一代码示例:
1234567891011121314151617181920212223242526272829class Solution {public: vector<int> plusOne(vector<int>& digits) { //从最后一位开始 for(int i = digits.size()-1;i>= 0;i--) { //最后一位不是9,+1直接return //如果此时后一位由9已经变成了0 //紧着这判断这位不是9,+1直接return,就相当于满10进1 if(digits[i]+1 != 10) { digits[i] += 1; return digits; } //最后一位加上1等于10 //变成0 digits[i] =0; ...
LeetCode刷题(13)【简单】最大子序和(C++)
最大子序和题目链接——最大子序和
代码示例:
12345678910111213141516171819202122232425最笨的方法: 依次从每个元素开始往后一个一个的相加,加到temp1中,如果比之前的大就存到temp2中,最后得到最大的和。 每轮完重置temp1class Solution {public: int maxSubArray(vector<int>& nums) { int temp1 = 0; int temp2 = INT_MIN; for(int i =0;i<nums.size();i++) { for(int j =i;j <nums.size();j++) { temp1 += nums[j]; if(temp1 >= temp2) { temp2 = temp1; ...
LeetCode刷题(12)【简单】最长公共前缀(C++)
最长公共前缀题目链接——最长公共前缀
代码示例:
123456789101112131415161718192021222324class Solution {public: string longestCommonPrefix(vector<string>& strs) { //容器为空 if(strs.size() == 0) { return ""; } for (int i = 0; i < strs[0].size(); i++) { char ch = strs[0][i]; for (int j = 1; j < strs.size();j++) { if (strs[j][i] != ch || i > strs[j].size()) ...