博文

《Thinking In C++》第2卷   更正(2009-08-01 09:58:00)

摘要:在《Thinking In C++》(第2卷)这本书中,第5章里面的Lookup2这个程序:   #include <algorithm>
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl; void g() { cout << "global g()" << endl; } template<class T> class Y {
public:
  void g() {
    cout << "Y<" << typeid(T).name() << ">::g()" << endl;
  }
  void h() {
    cout << "Y<" << typeid(T).name() << ">::h()" << endl;
  }
  typedef int E;
}; typedef double E; template<class T> void swap(T& t1, T& t2) {
  cout << "global swap" << endl;
  T temp = t1;
  t1 = t2;
  t2 = temp;
} template<class T> class X : public Y<T> {
public:
  E f() {
    g();
    this->h();
    T t1 = T(), t2 = T(1);
  &n......

阅读全文(2285) | 评论:2

C++读书笔记——typeid操作符(2009-08-01 09:22:00)

摘要:typeid操作符      typeid表达式形如:       typeid(expr); 这里expr是任意表达式或者类型名。如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。      typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件typeinfo中定义)。标准并没有确切定义type_info,它的确切定义编译器相关的,但是标准却规定了其实现必需提供如下四种操作:  t1 == t2  如果两个对象t1和t2类型相同,则返回true;否则返回false  t1 != t2  如果两个对象t1和t2类型不同,则返回true;否则返回false  t.name()  返回类型的C-style字符串,类型名字用系统相关的方法产生  t1.before(t2)  返回指出t1是否出现在t2之前的bool值type_info类提供了public虚析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符(由此可见,如果把typeid看作函数的话,其应该是type_info的友元)。type_info的name成员函数返回C-style的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这是由实现所决定的,标准只要求实现为每个类型返回唯一的字符串。例如: #include <iostream>

using namespace std;

class Base {};
class Derived: public Base {};

int main()
{
&......

阅读全文(10898) | 评论:3

编程比赛——狼能否找到兔子?(转)(2009-07-31 22:15:00)

摘要:/**********************************************************************************************************************************
一座山上周围有n个洞,顺时针编号为0,1,2,……,n-1。
而一只狼从0号洞开始,顺时针方向计数,每遇到m个洞就进洞找兔子,
例如n=5 m=3 狼经过的洞依次为0,3,1,4,2,0
输入n、m。试问兔子有没有幸免的机会? 编写一个完整的程序  n m 由scanf输入 有幸免的机会输出Y
没有输出N ***********************************************************************************************************************************/
#include<iostream>
using namespace std;
/*
因为题目没给出n的范围,所以我只设了长度为1001
只能测n<=1000的情况 具体情况请题主自由设定tag长度
*/
int deal(int m,int n,int tag[])
{
    int drift(m);
    int count(1);
    while(drift!=0)
    {
        if(drift>=n)
            drift=drift%n;
        if(0==tag[drift])
      &nb......

阅读全文(2063) | 评论:7

标准库 STL :Allocator能做什么?(2009-07-24 21:40:00)

摘要:1 什么时候不使用Allocator 参考资料:STL China C++标准中的Allocator分成两块:一个通用需求集(描述于§ 20.1.5(表 32)),和叫std::allocator的class(描述于§20.4.1)。如果一个class满足表32的需求,我们就称它为一个 allocator。std::allocator类满足那些需求,因此它是一个allocator。它是标准程序库中的唯一一个预先定义 allocator类。 每个 C++程序员都已经知道动态内存分配:写下new X来分配内存和创建一个X类型的新对象,写下delete p来销毁p所指的对象并归还其内存。你有理由认为allocator会使用new和delete--但它们没有。(C++标准将::operator new()描述为“allocation function”,但很奇怪,allocator并不是这样的。) 有关allocator的最重要的事实是它们只是为了一个目的:封装STL容器在内存管理上的低层细节。你不应该在自己的代码中直接调用allocator 的成员函数,除非正在写一个自己的STL容器。你不应该试图使用allocator来实现operator new[];这不是allocator该做的。 如果你不确定是否需要使用allocator,那就不要用。 allocator 是一个类,有着叫allocate()和deallocate()成员函数(相当于malloc和free)。它还有用于维护所分配的内存的辅助函数和指示如何使用这些内存的typedef(指针或引用类型的名字)。如果一个STL容器使用用户提供的allocator来分配它所需的所有内存(预定义的 STL容器全都能这么做;他们都有一个模板参数,其默认值是std::allocator),你就能通过提供自己的allocator来控制它的内存管理。 这种柔性是有限制的:仍然由容器自己决定它将要申请多少内存以及如何使用它们。在容器申请更多的内存时,你能控制它调用那个低层函数,但是你不能通过使用 allocator来让一个vector行动起来像一个deque一样。虽然如此,有时候,这个受限的柔性也很有用。比如,假设你有一个特殊的 fast_allocator,能快速分配和释放内存(也许通过放弃线程安全性,......

阅读全文(2549) | 评论:0

C++ 宏定义 点点滴滴(2009-07-23 10:53:00)

摘要:C++提供的编译预处理功能主要有以下三种:
  (一) 宏定义
  (二) 文件包含
  (三) 条件编译

在C++中,我们一般用const定义符号常量。很显然,用const定义常量比用define定义常量更好。
  在使用宏定义时应注意的是:
  (a) 在书写#define 命令时,注意<宏名>和<字符串>之间用空格分开,而不是用等号连接。
  (b) 使用#define定义的标识符不是变量,它只用作宏替换,因此不占有内存。
  (c) 习惯上用大写字母表示<宏名>,这只是一种习惯的约定,其目的是为了与变量名区分,因为变量名
                    通常用小写字母。
  如果某一个标识符被定义为宏名后,在取消该宏定义之前,不允许重新对它进行宏定义。取消宏定义使用如下命令:
  #undef<标识符>
  其中,undef是关键字。该命令的功能是取消对<标识符>已有的宏定义。被取消了宏定义的标识符,可以对它重新进行定义。
  宏定义可以嵌套,已被定义的标识符可以用来定义新的标识符。例如:
  #define PI 3.14159265
  #define R 10
  #define AREA (PI*R*R)
单的宏定义将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来代替。前面已经说过,预处理命令不同于一般C++语句。因此预处理命令后通常不加分号。这并不是说所有的预处理命令后都不能有分号出现。由于宏定义只是用宏名对一个字符串进行简单的替换,因此如果在宏定义命令后加了分号,将会连同分号一起进行置换。

带参数的宏定义
  带参数的宏定义的一般形式如下:
  #define <宏名>(<参数表>) <宏体>
  其中, <宏名>是一个标识符,<参数表>中的参数可以是一个,也可以是多个,视具体......

阅读全文(2542) | 评论:0