Archive for ‘之语言特性’ Category

November 18, 2011

  我们还知道,类的静态成员函数是不需要绑定到特定对象上面的,所以我们就可以将worker声明为静态成员。

1
2
3
4
5
6
7
8
9
10
11
class Thread
{
public:
    static void* worker(void* args) {
        //~ thread execution.
    }
private:
    //~ here some data member.
};
pthread_t tid;
pthread_create(&tid, NULL, &Thread::worker, NULL);

  我们又知道,静态成岩函数是不能’直接’访问类的非静态成员(包括函数),因此,上面代码中worker即使属于class Thread的类域,但却无法访问这个类的成员,这让人十分不爽。哪位大牛说过来着?任何一个复杂的计算机问题,都可以通过中间层来解决。这里也可以建立一个中间层:使用静态成员函数创建线程,给该函数传递某个对象的地址作为参数,在该静态函数中就可以通过所传递对象的使用它的任何成员了。

Tags: ,. 136 views
August 7, 2011

使用变参

  C/C++提供了函数的可变参数(variadic)机制,大部分人写的第一个C程序恐怕就是Hello World吧,使用的应该也是printf(“Hello, World\n”)。printf就是一个使用可变参数的典型,它的原型声明为,

int printf(const char *fmt, ...);

  其中返回值为实际输出字符个数,fmt为格式控制字符串,而”…”便声明了一个可变参数,你可以根据传递0个或多个参数给printf。printf内部会根据格式控制串中的格式指定符号(d, f, p等等)来逐个解析通过可变参数传进的实参变量。
  为解析可变参数,C语言提供了一个va_list类型和四个宏,分别是va_start, va_arg, va_end, 和va_copy,这些宏声明在stdarg.h中。

Tags: ,,. 268 views
May 6, 2011

  关于虚函数,需要知道:

  • 多态在C++中借助虚函数实现
  • 多态只在指针或者引用上发生
  • 虚函数机制(通常)借助虚指针vptr支持
  • 虚函数地址保存在虚函数表中
  • 一个类的所有对象共有一张vtbl
  • vtbl由vptr指向,vptr保存在每一个对象中,多继承时可能有多个vptr
  • vptr由构造函数(普通构造/copy构造)在对象初始化时隐式设定
Tags: ,. 192 views
April 25, 2011

  reserve内部是怎么实现的呢?当然是new了。那么在reserve操作,也就是new之后,我们程序是否立即就占用了这些内存呢?这就要看我们这里说的“内存”是什么样的内存了。什么意思呢?我们知道,现代操作系统都采用了虚拟内存的机制,内存占用也就有了虚拟内存(virtual memory)和物理内存(physical memory)之分了。
  我们又知道,Unix/Linux进程的虚拟地址空间被按用途被划分成了内核空间和用户空间。内核空间供操作系统的内核使用,用户空间供用户程序支配。其中用户空间又被划分为若干段,主要包括:代码段(.text),用来存放/映射用户程序的代码;数据段(.data),存放初始化的全局数据或静态数据,这部分在文件系统中也占据磁盘空间;.bss段(一直没找到一个亲切的翻译),存放为初始化的全局或静态数据,在程序加载时分配空间和初始化,这部分空间不占用磁盘空间(当然在可执行文件中要保留其大小);堆栈段,用来保存程序执行时的上下文(局部变量、函数参数和返回地址等),在进程建立时由操作系统分配,空间较小且在运行时不可动态调整,增长方向因机器架构而异,IA上自高地址向下增长,堆栈不占用磁盘空间;堆,供用户在运行时动态地申请和使用,空间较大,未被申请的堆空间不可使用,也不会被映射到物理空间,堆随着用户程序申请向上增长,堆不占用磁盘空间。

Tags: ,,. 177 views
April 10, 2011

  关于C++ STL容器的默认内存管理,需参考allocator。
  关于deque的内存模型及其clear操作,我不甚了了,请参考您使用的标准库的代码。
  若想深入了解STL的实现,侯捷大叔的《STL源码剖析》是不错的入门资料,希望能够拜读。
  C++标准中并未对STL的实现细节做过多规定,因此不同实现的细节和表现可能不同。

  C++很复杂,但也并非无底黑洞。学好C++很难,但这种学习过程也会使你收获颇丰。
  学习任何一种技术,都需要热情、激情和足够的耐心。
  做好一件事,需要激情,同时激情常常来源于做好一件事情的满足感。
  满足感会增强人分享的欲望,分享的欲望也常常会使人具有亲和力和感染力,使人觉得你有激情,反过来更有利于人做好一件事。
  blabla, over~

Tags: ,. 855 views
April 9, 2011

  头文件中通常包含有:函数原型(声明)、宏定义、内联函数定义。
  头文件使用#include宏命令引入。有两种形式:#inlcude <header.h>和#include “header.h”. 两种形式的区别在于预处理器(preprocessor)查找头文件的方式的不同:对于前者,预处理器仅在系统预定义的标准路径中查找(标准查找路径由环境变量指明),比如/usr/include, /usr/local/include;对于后者,预处理器首先查找(源文件所在的)当前目录,若未找到,则到标准路径查找。另外,查找路径还可以通过编译器选项(-I for gcc)指定。通常,对于C/C++标准库和其他系统范围的程序库,使用<>形式,对于程序本身定义的头文件,采用”"形式。

Tags: ,. 126 views
October 22, 2010

  不多说,都在代码里了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int
main(int AC, char **AV)
{
    FILE *fd = fopen("data", "w+");
    fprintf(fd, "%x%c", 0x41, '1');
    fseek(fd, 0, SEEK_SET);
    int n;
    fscanf(fd, "%d", &n);
    fseek(fd, 0, SEEK_SET);
    char s[4];
    int c = fread(s, 1, sizeof(s), fd);
    s[c] = '\0';
    printf("%d, %s\n", n, s);
    fclose(fd);
    return 0;
}
Tags: . 202 views
October 5, 2010

  在StackOverflow上面看到的,分析一下下面的代码,对初学者理解什么是堆,什么是栈,对象是如何拷贝的有所帮助。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
typedef struct node
{
      int i;
      struct node *next;
}node;
node getnode(int a)
{
      struct node n;
      n.i=a;
      n.next=NULL;
      return n;
}
Tags: . 256 views
September 20, 2010

  在很多C/C++头文件中,你可能会经常看到使用extern “C”{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容?C++对C本来不就是兼容的吗?确实,在语法层面,C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容,包括两种情况下的兼容。一种是,在C++代码中调用已经存在的C代码写成的库;另一种是,使用C编写代码,而希望这些代码能够使C++可以调用。
  若想继续讨论extern “C”,就不得不提name mangling。
  我们知道,相比C,C++支持函数重载,支持命名空间,支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数,命名空间(namespace)和类为名字(或者说符号)划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性,C++就使用了name mangling。即是说,C++编译器在编译C++文件时,把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字(因为汇编级别的代码中,所有符号都在同一个域)。由于C中并不存在这些特性,所以通常C编译器并不对符号进行mangling。

Tags: ,. 318 views
September 19, 2010

  那么,C/C++中,哪些地方是顺序点呢?

  • 每个表达式的结束处;
  • 函数调用中,在所有参数求值完成后,函数体开始执行前有一个顺序点,而参数间的逗号处则没有顺序点。所以f(++i, ++i)的行为也是未定义的;
  • 逻辑运算符&&、||还有条件运算符?:的第一个参数末尾处有一个顺序点;
  • 逗号表达式中每一个逗号处有一个顺序点。因此x = (++i, ++i)是有确定行为的;
  • 在每一个完整的变量声明处有一个顺序点,例如int i, j;中逗号和分号处分别有一个顺序点;
  • for循环控制条件中的两个分号处各有一个顺序点。

  那么,现在,这个程序有问题吗?

1
2
3
4
5
6
7
8
9
int
main()
{
    int m = 1, n = 0;
    printf("%d, %d\n", m, n);
    m ^= n ^= m ^= n;
    printf("%d, %d\n", m, n);
    return 0;
}
Tags: ,,. 253 views
Page 1 of 9123456789