只占了十分之一左右!这又是为什么呢?永远也学不完的虚拟内存啊!
呃……又SB了!const int size = 2^30;这哪里是1G啊!分明是28嘛!Orz…汇编码里面尽是28!这下好了,改成1<<30,运行了四个实例,机器就笨的像猪了:
等程序结束了,刚开始运行着到浏览器也慢了一会儿,估计是被换到交换文件里面去了。
熟读而精思,循序而渐进,厚积而薄发。
只占了十分之一左右!这又是为什么呢?永远也学不完的虚拟内存啊!
呃……又SB了!const int size = 2^30;这哪里是1G啊!分明是28嘛!Orz…汇编码里面尽是28!这下好了,改成1<<30,运行了四个实例,机器就笨的像猪了:
等程序结束了,刚开始运行着到浏览器也慢了一会儿,估计是被换到交换文件里面去了。
我试图以二进制的方式打开文件movie.avi,并复制到另外一个文件film.avi,于是写了下面的一段代码。问题是,这段代码只对某些文件适用,而无法”完全”复制另外一些文件,也就是说,当源文件并没有读完时却已经提前结束了。我想应该是某一个特殊字节的值导致read认为文件已经读完了,但我是以二进制方式打开的文件呀,这种情况下,文件结束符EOF还有意义吗?puzzling……
/*
* 此处循环判断的原因如下:假设2个线程在getq阻塞,然后两者都被激活,
* 而其中一个线程运行比较块,快速消耗了2个数据,
* 另一个线程醒来的时候已经没有新数据可以消耗了。
* 另一点,man pthread_cond_wait可以看到,
* 该函数可以被信号中断返回,此时返回EINTR。
* 为避免以上任何一点,都必须醒来后再次判断睡眠条件。
* 更正:pthread_cond_wait是信号安全的系统调用,不会被信号中断。
*/
表明看来似乎合情合理,由于C++的多态特性,允许我们将一个子类地址赋给父类型的指针pb,释放对象时理所当然的对pb进行delete。但,在程序运行时,并没有输出M destructed…,即D::m的析构函数没有被调用,而m的析构函数是需要D::~D()来调用的,所以子类D的析构函数也没有被调用。这是很容易理解的,因为父类的析构函数不是virtual的。由此,我们得出结论,用来继承的父类的析构函数总应该是virtual的,除非你确定它绝对不会被用于多态。关于这一点,《Effective C++》里面已经讲到了。
除了上面的问题,我们还应该关心的是,尽管析构函数没有被调用,那M::i的空间被释放了吗?It’s a question!由于析构函数没有被调用,那么释放M::i的任务就完全落在了delete身上的了,那么delete做到了吗?It’s a very question!这又回到了上一篇日志中所描述的问题上了。我的观点是delete做到了它应该做的事情,它只负责释放当初new申请的空间,即对象本身,至于对象里面是否有动态申请的内存,那就不是delete而是对象析构函数自己的工作了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int main() { pthread_mutex_init(&mutex, NULL); //~ 初始化互斥锁mutex pthread_t thread_id; void *exit_status; pthread_create(&thread_id, NULL, thread_function, NULL); //~ 创建新线程 for(int i = 0; i < 10; ++i) { usleep(10000); //~ 延时10ms //~ 访问共享数据 pthread_mutex_lock(&mutex); cout<<share<<endl; pthread_mutex_unlock(&mutex); } pthread_join(thread_id, &exit_status); //~ 等待线程结束 pthread_mutex_destroy(&mutex); //~ 销毁互斥锁 return 0; } |
源码之前,了无秘密。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //~ demo.cpp #include <iostream> #include <fstream> #include <string> #include <streambuf> using namespace std; //~ 测试代码 :) int main() { ifstream in("demo.cpp"); char buffer[4096]="original content in this buffer"; cout<<buffer<<endl; streambuf * ptrbuff = in.rdbuf(); //~ 将streambuf与文件句柄关联 ptrbuf->pubsetbuf(bufer, 4096); //~ 设置缓冲区,即设置in的缓冲区 cout<<buffer<<endl; //~ 此时bufer里面的内容还是original content in this buffer string str; in>>str; //~ 真正要输入时bufer才被填充为in的内容 cout<<str<<endl; cout<<buffer<<endl; return 0; } |
另外,还有一个filebuf,用法相近。看了很多C++方面的书,从来没有那本书对I/O流做过详细的介绍。C里面有setbuf可以修改缓冲区,但我在fstream里面却没看到这么个setbuf,rdbuf倒是有一个,它返回streambuf类型的指针。搜索streambuf的用法,无果,MSDN里面看到streambuf有一个setbuf的成员,甚喜。编译器说,setbuf是私有的,再看MSDN,还有一个pubsetbuf,哟西!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void reverse(Node * T) { assert(T); //~ 表头非空 Node* p = T->next, *t; if(p) { //~ 将第一个结点,即未来的表尾next域置空 t = p->next; p->next = NULL; p = t; } while(p) { //~ 将余下结点依次插入表头 t = p->next; p->next = T->next; T->next = p; p = t; } } |
有一点需要注意的是,由于STL内的容器的析构函数都不是virtual的,所以,继承这些容器的类(或者模板类)不能用于多态!这也是不提倡继承STL容器的原因。
不过,由于上面的代码中mstack
继承vector的目的不是使用多态特性,仅仅是复用了vector的接口而已,且复用也仅仅是内部复用;
由于是私有继承,你无法调用父类vector的接口,子类与父类接口并不一致,在语法就不能用于多态;
综上所述,这样的继承并没有什么潜在的危险。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | template <class T> class Queue { public: Queue(int size = 30); ~Queue(); void EnQueue(T value); T DeQueue(); T GetFirst(); bool IsEmpty(); bool IsFull(); void ClearQueue(); private: T *queue; int front; int rare; int MaxSize; int CurLen; }; |
一个堆栈类模板,和用到此模板的一个表达式计算器。
输入四则运算表达式(可含括号),输出计算结果,暂未提供盛放运算和浮点数功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Stack { public: Stack(int stack_size = 30); ~Stack(); void Push(T value); T Pop(); T Top(); bool IsEmpty(); bool IsFull(); void ClearStack(); private: int top; T* stack; int size; }; |