指针变量

智能指针与句柄类(二)

心已入冬 提交于 2020-03-30 16:44:12
   之前文章 提到写时复制(copy-on-write)技术,要实现这种功能,针对上文中Handle代码,需要将size_t * use这个抽象出来,封装成一个引用计数类,提供写时复制功能。CUseCount类实现如下: 1 class CUseCount 2 { 3 public: 4 CUseCount(); 5 CUseCount(const CUseCount&); 6 ~CUseCount(); 7 8 bool only()const; //判断引用计数是否为0, 句柄类无法访问private int*p, 故提供此函数 9 bool reattach(const CUseCount&); //对计数器的操作, 用来代替 operator = 10 11 bool makeonly(); //写时复制, 表示是否需要赋值对象本身 12 13 private: 14 CUseCount& operator=(const CUseCount&); //提供reattach函数代替 operator = 15 int *p; //实现计数 16 }; 17 18 CUseCount::CUseCount():p(new int(1)) 19 {} 20 21 CUseCount::CUseCount(const CUseCount& u):p(u.p) 22 { 23 ++

类的this指针

空扰寡人 提交于 2020-03-30 16:42:35
   类的this指针有以下特点:    (1)this只能在成员函数中使用。   全局函数、静态函数都不能使用this。   实际上,成员函数默认第一个参数为T* const this。   如: class A{public: int func(int p) {}}; 其中,func的原型在编译器看来应该是: int func(A* const this, int p); (2)由此可见,this在成员函数的开始前构造,在成员的结束后清除。   这个生命周期同任何一个函数的参数是一样的,没有任何区别。   当调用一个类的成员函数时,编译器将类的指针作为函数的this参数传递进去。如: A a;a.func(10); 此处,编译器将会编译成: A::func(&a, 10); 看起来和静态函数没差别,对吗?不过,区别还是有的。编译器通常会对this指针做一些优化,因此,this指针的传递效率比较高——如VC通常是通过ecx寄存器传递this参数的。    (3)几个this指针的易混问题。    1)this指针是什么时候创建的?   this在成员函数的开始执行前构造,在成员的执行结束后清除。   但是如果class或者struct里面没有方法的话,它们是没有构造函数的,只能当做C的struct使用。采用TYPE xx的方式定义的话,在栈里分配内存

C++ 指向数组的指针

僤鯓⒐⒋嵵緔 提交于 2020-03-30 16:08:14
如果您对 C++ 指针的概念有所了解,那么就可以开始本章的学习。数组名是一个指向数组中第一个元素的常量指针。因此,在下面的声明中: double balance[50]; balance 是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。因此,下面的程序片段把 p 赋值为 balance 的第一个元素的地址: double *p; double balance[10]; p = balance; 使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。 一旦您把第一个元素的地址存储在 p 中,您就可以使用 *p、*(p+1)、*(p+2) 等来访问数组元素。下面的实例演示了上面讨论到的这些概念: #include <iostream> using namespace std; int main () { // 带有 5 个元素的整型数组 double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0}; double *p; p = balance; // 输出数组中每个元素的值 cout << "使用指针的数组值 " << endl; for ( int i = 0; i < 5; i++ ) { cout << "*(p + " <<

数组指针和指针数组的区别

别说谁变了你拦得住时间么 提交于 2020-03-30 14:25:57
数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。 如要将二维数组赋给一指针,应这样赋值: int a[3][4]; int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][] 所以数组指针也称指向一维数组的指针,亦称行指针。 指针数组 定义 int *p[n]; []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针 for(i=0;i<3;i++) p[i]=a

马哥博客作业第二周

≡放荡痞女 提交于 2020-03-30 08:16:44
3月23日课程:文件管理 1. 相对路径:一般情况下相对的是当前所在的目录! *特殊情况下也可能不是相对于当前目录而是相对于某个目录。 2. Ls 命令 及其各选项 3. Sata 查看三个文件时间 所有者 大小 节点等! modify time 修改文件内容时间 change time 属性更改时间 所有者或文件类型 access time 文件读取时间。 4. Chown 更改文件所有者 change owner 5. File + 文件 查看文件类型 6. Linux对文件后缀要求不严格,更改后缀依然可以用。 7. Linux和windows文件格式不一样,相互需要转换才能使用。dos2unix 可以将windows格式改成linux格式,unix2dos linux格式改成 windows格式。 8. Hexdump 看文件2进制内容 9. 编码 中国 GB2312 全球utf8 10. 文件通配符 文件通配符可以用来匹配符合条件的多个文件,方便批量管理。文件通配符采有特定的符号,表示特定的含义 11. cp 选项属性 cp -a 常用于备份 特殊文件一定要保存属性复制 复制整个文件包括隐藏文件 .开头的文件 只复制隐藏文件 12. mv 移动文件 更改位置 也可以改名 ,同一分区移动数据,速度很快:数据位置没有变化。不同分区移动数据,速度相对慢:数据位置发生了变化 13.

2020.3.23第四次作业

你说的曾经没有我的故事 提交于 2020-03-30 02:58:57
一、学习笔记 学习范围:3.2.1结构类型、3.2.2结构与函数、3.2.3 结构中的结构 二、相关程序 三、遗留问题 对于以下结构定义, ++p->str 中的 ++ 加在__ D __。 (2分) struct { int len; char *str; } *p; A. 指针str上 B.指针p上 C.str指的内容上 D.以上均不是 解析:p是一个结构体指针,结构体指针访问成员用"->",结构体变量用"." 来源: https://www.cnblogs.com/qipaopao001120/p/12571345.html

C++类内存分布

房东的猫 提交于 2020-03-30 02:39:27
转自:http://www.cnblogs.com/jerry19880126/p/3616999.html C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承、虚函数存在的情况下。 工欲善其事,必先利其器,我们先用好Visual Studio工具,像下面这样一步一步来: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。近期的VS版本都支持这样配置。 下面可以定义一个类,像下面这样: 1 class Base 2 { 3 int a; 4 int b; 5 public: 6 void CommonFunction(); 7 }; 然后编译一下,可以看到输出框里面有这样的排布: 这里不想花精力在内存对齐因素上,所以成员变量都设为int型。 从这里可以看到普通类的排布方式,成员变量依据声明的顺序进行排列(类内偏移为0开始),成员函数不占内存空间。 再看下继承,往后面添加如下代码: 1 class DerivedClass: public Base 2 { 3 int c; 4 public

C++四种强制转换

梦想的初衷 提交于 2020-03-30 02:37:35
C语言的强制转换为在数据面前之间加数据类型进行转换,即(目标数据类型)原数据类型。 c++ 为了更好的 区分强制转换的类型 ,达到 见其名知其意 的效果,共将强制转换分为四种,即 1、static_cast<目标数据类型>原数据类型 2、const_cast<目标数据类型>原数据类型 3、reinterpret_cast<目标数据类型>原数据类型 4、dynamic_cast<目标数据类型>原数据类型 解析 static_cast<>() 1)用于类层次结构中基类和派生类之间指针或引用的转换 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的 进行下行转换(把基类的指针或引用转换为派生类表示),由于没有动态类型检查,所以是不安全的 2)用于基本数据类型之间的转换,如把int转换成char。这种转换的安全由开发人员来保证 3)把空指针转换成目标类型的空指针 4)把任何类型的表达式转换为void类型 注意:static_cast不能转换掉expression的const、volitale或者__unaligned属性。  static_cast:可以实现C++中内置基本数据类型之间的相互转换。 如果涉及到类的话,static_cast只能在 有相互联系的类型中进行相互转换, 不一定包含虚函数。 const_cast<>() cost_cast即用于强制转换 指针或者引用 的

Debug版本和Release版本的区别

这一生的挚爱 提交于 2020-03-29 19:17:15
一、Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。 Debug 和 Release 的真正秘密,在于一组编译选项。下面列出了分别针对二者的选项(当然除此之外还有其他一些,如/Fd /Fo,但区别并不重要,通常他们也不会引起 Release 版错误,在此不讨论) Debug 版本: /MDd /MLd 或 /MTd 使用 Debug runtime library(调试版本的运行时刻函数库) /Od 关闭优化开关 /D "_DEBUG" 相当于 #define _DEBUG,打开编译调试代码开关(主要针对 assert函数) /ZI 创建 Edit and continue(编辑继续)数据库,这样在调试过 程中如果修改了源代码不需重新编译 /GZ 可以帮助捕获内存错误 /Gm 打开最小化重链接开关,减少链接时间 Release 版本: /MD /ML 或 /MT 使用发布版本的运行时刻函数库 /O1 或 /O2 优化开关,使程序最小或最快 /D "NDEBUG" 关闭条件编译调试代码开关(即不编译assert函数) /GF 合并重复的字符串,并将字符串常量放到只读内存,防止 被修改

一些面试题,转关注的一个博客

一个人想着一个人 提交于 2020-03-29 12:13:37
腾讯面试题: tcp 三次握手的过程, accept 发生在三次握手哪个阶段? 答accept发生在三次握手之后。 第一次握手:客户端发送syn包(syn=j)到服务器。 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个ASK包(ask=k)。 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。 三次握手完成后,客户端和服务器就建立了tcp连接。这时可以调用accept函数获得此连接。 const 的含义及实现机制,比如: const int i, 是怎么做到 i 只可读的? const用来说明所定义的变量是只读的。 这些在编译期间完成,编译器可能使用常数直接替换掉对此变量的引用。 用 UDP 协议通讯时怎样得知目标机是否获得了数据包 可以在每个数据包中插入一个唯一的ID,比如timestamp或者递增的int。 发送方在发送数据时将此ID和发送时间记录在本地。 接收方在收到数据后将ID再发给发送方作为回应。 发送方如果收到回应,则知道接收方已经收到相应的数据包;如果在指定时间内没有收到回应,则数据包可能丢失,需要重复上面的过程重新发送一次,直到确定对方收到。 求一个论坛的在线人数,假设有一个论坛,其注册 ID 有两亿个,每个 ID 从登陆到退出会向一个日志文件中记下登陆时间和退出时间