0%

最近在看《深度探索c++对象模型》对于对象模型有了一点了解,做一个总结。以下的一些结论的实验见:https://github.com/xtestw/CPPObjModelTest

单个对象模型

对于一个单个对象而言,对象的内部结构是类似于一张表结构,依次存储着c++的对象内部数据,我们都知道,一个c++的类内部一般会包含下面的几个部分:

  • 非静态成员变量
  • 非静态成员函数
  • 静态成员变量
  • 静态成员函数
  • 虚函数
  • 友元函数
  • 构造函数、析构函数、拷贝构造函数

对于一个简单的对象,将设我们定义类如下:

1
2
3
4
5
6
7
8
9
10
class base{
public:
base();
virtual ~base();
int a,b;
void f();
static int c,d;
static void f2();
virtual void f3();
};

不考虑继承的话,他们的存储结构会是这样的一个结构,如下图: 其中,非静态数据成员,被放在对象的内部,而虚函数会放在对象的一个虚表中,对象在编译的时候会形成一个vptr的指针置于对象的内部,其指针指向这张虚表(考虑类的继承和多态,指向这张虚表的vptr的设置和重置会在构造函数、析构函数和拷贝函数中自动完成)。 对象在图对象表中的位置,是按照对象的申明顺序来排列的。比如a,b的申明,因为a先申明的,那么a就被先压栈,占据高地址。 而如图所见,不论虚函数是多少个,对象内部只有一个指针指向它,所以始终占一个指针大小的空间(32位机器下是4byte). 而对这个vptr在对象中的位置,不同的编译器的处理是不一样的,vc为代表的是将其放在了头部,而gcc等则是将其放在了对象的尾部,放在尾部是为了综合考虑与C的struct的兼容问题,而在头部,则是考虑继承之后的子类在调用vptr的方便性。(我个人更偏向于放在头部,因为这样在继承的时候更好理解也更方便自然),本文中的代码和模型是基于g++编译器做的实验,都是放在头部的。 还有一个问题,《深度探索c++对象模型》中,对这个1byte的类的type_info位置,他是说放在虚表的第一个位置,而其实g++中,下面这个实验,并不是放在虚表中的:

阅读全文 »

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-nohup/ 我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败。如何让命令提交后不受本地关闭终端窗口/网络断开连接的干扰呢?下面举了一些例子, 您可以针对不同的场景选择不同的方式来处理这个问题。

nohup/setsid/&

场景:

如果只是临时有一个命令需要长时间运行,什么方法能最简便的保证它在后台稳定运行呢?

hangup 名称的来由

在 Unix 的早期版本中,每个终端都会通过 modem 和系统通讯。当用户 logout 时,modem 就会挂断(hang up)电话。 同理,当 modem 断开连接时,就会给终端发送 hangup 信号来通知其关闭所有子进程。

阅读全文 »

http://xtestw.site/?p=29

##x&(-x)取x的最后一个1的证明##
明天要给新队员讲树状数组,避不开的一个证明,之前教主讲过,当时没听明白给忘了- -,只有自己想了一种证明方法。

#####证明#####
大家都知道,计算机是用补码来存储一个数的,在这种编码情况下,整数是自然状态编码,假设我们是一个5位的机器(只是假设),那么1,编码就为00001, 而-1的编码则是11111(并不是10001),在这种情况下,我们会有下面的结论:

             -x=11111 – x +1 (x 假设为正数二进制)  -----------------结论一
              x=00000 + x (x 假设为正数二进制) ----------------------结论二

我们还会有以下2个结论:

结论三:11111 - x 不会出现借位的情况(二进制下 ,对应位只会是两种情况 1-0 和 1-1)
结论四:00000 + x 不会出现进位的情况(二进制下,对应位只会是 0+1,0+0)

假设 x的二进制编码为 x1 x2 x3 x4 x5

那么我们就会发现 对于任何一位(以x1为例) 0+x1 和 1-x1 两个 必然是一个为1 一个为0,因为:

X1的值 0+x1 1-x1
0 0 1
1 1 0
阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class base{
public:
int i,j;
base(){
i=j=0;
}

base(int a,int b){
i=a;j=b;
}
};

class derived:public base{
public:
derived(int a,int b){
base(a,b);
}
};

int main(){
  derived d(3,1);
  cout<<d.i<<" "<<d.j<<endl;
  return 0;
}

上面的这段代码会输出什么呢?!正确的答案是输出了”0 0”. 我的理解是,虽然其中调用了base(a,b) 但是其实操作的a和b不是当前d的a,b,其实是定义了一个新的base的对象。正确的写法应该是下面这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class base{
public:
int i,j;
base(){
i=j=0;
}
base(int a,int b){
i=a;j=b;
}
};



class dervied:public base{

public:
derived(int a,int b):base(a,b){
}
};

int main(){
  derived d(3,1);
  cout<<d.i<<" "<<d.j<<endl;
  return 0;
}

关于c++构造函数两个误解

  1. 任何class只要没有定义构造函数,就会被编译器自动合成一个。 有些构造函数在实际中有和没有是没有任何用处的,所以无用的构造函数是不会被构建出来

  2. 编译器合成的构造函数,会为每个成员变量设定初始值 在我看来,编译器合成的构造函数,是为了调用成员类或者父类的构造函数,而这个成员类的构造函数的调用顺序则是按照申明的顺序来调用。

1、assigned

主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。

“ud”是自定义的策略名,人为起的名字,后面均用“ud”表示。

特点:可以跨数据库,人为控制主键生成,应尽量避免。

2、increment

由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。

Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。

阅读全文 »

1.常见的错误返回类型

VOID/BOOL/HANDLE/PVOID/LONG/DWORD VOID 不可能失败 BOOL 错误返回false 编码的时候最好测试是否不为FALSE HANDLE 错误 NULL/INVALID_HANDLE_VALUE PVOID  失败返回NULL,成功返回一个数据块的地址 LONG/DWORD 0或-1,不绝对 2.GetLastError函数   DWORD GetLastError(); 3.WinError.h 头文件定义了若干的Mircosoft定义的代码列表 4.

IOCP是windows下的一种异步IO通信模式(linux下面对应epoll,二者有区别—>http://www.cnblogs.com/uzhang/archive/2012/02/24/2365980.html)

一样的socket的绑定通信的过程,不同的是并不对每一个用户请求单独开设一个线程去处理用户请求,而是在后面一线程池的方式,开固定的线程,轮流处理用户请求,减少线程的上下文切换损耗,同时利用重叠IO,减低内存等资源的消耗。 关于具体的一些内容,见:http://blog.csdn.net/neicole/article/details/7549497

学校课程需要找一份代码,来讲讲代码里面用了哪些设计模式- -! 还是要java的。。。 于是上github上面翻代码,偶然翻到一个java的xchart图标库,感觉可能以后会用的到,而且代码不是很长,就直接拿过来用了。具体的链接地址如下:https://github.com/timmolter/XChart

先看文件夹结构:
image          

一共有6个包,最后一个是用来测试的包,可以忽略不计,一共5个包,5个包的作用分别是

  • com.xeiam.xchart:
    主要是图表生成的代码以及一些图表的功能包括导出功能的代码,是给我们使用该jar包人调用的结构,表示的是一个图表整体的构造,包括Chart,ChartBuild,Series等类。
    image

  • com.xeiam.xchart.internal
    这个package里面只有两个类,一个是package-info,我也不是很明白他的作用。。。就是写了一个license的地址。另一个类是Utils的类,提供了两个静态方法,一个求幂的,一个就是求差值的一半。

阅读全文 »

在实际开发的时候,我们同样的一个对象,对于不同的客户,可能能够调用的方法是不一样的,就是权限的控制,这个时候,对象的方法都应该是public,那么就要给对象加上一层,通过客户的类型,决定是否可以访问,也就是说,客户不直接访问对象,而是访问给对象加上的这一层,就是代理层。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public interface T1{
public void method();
};
public class Item implements T1{
public void method();
}
public class ItemProxy implements T1{
Item item;
Client client;
public ItemProxy(Client c){
this.Client=c;
this.item=new item();
}
public void method(){
if (client,allow()){
item.method1();
}else{
return;
}
}
}
public class Client{
T1 t;
public Client()
{
t=new ItemProxy(this);
}
public void method1()
{
t.method();
}
}

这样就可以在代理类中,控制对象的访问了,当然代理模式实现方式还有很多种,(远程代理管理客户和远程对象的交互,虚拟代理控制访问实例化开销大的对象,保护代理基于调用者控制对对象方法的访问),上面只是其中的一种方式,代理模式的定义如下:

阅读全文 »
×