泛型程式设计(Generic Programming)

元智大学 92-2 课程备忘录

侯捷

请注意:这里只是备忘录,不是完整教材或学习或讨论的地方。

每周三 18:30~21:20
工程一馆1102


课程教材(5 为教材,1,2,3,4,6,7,8 为辅助资料或书籍):

   1.《C++ Primer 3e》by Lippman & Lajoie. chap6,10,12,15,16, appnedix
   2.  "STL系列文章" by 侯捷,共五篇,见左视窗目录大标题(白色)
   3.《泛型程式设计与STL》, "Generic Programming and the STL" by Matthew H. Austern.
   4.《C++ 标准程式库》, "The C++ Standard Library", by Nicolai M. Josuttis.
* 5.《STL源码剖析》by 侯捷
   6.《C++ Templates 全览》, "C++ Tempaltes", by Vandevoorde & Josuttis.
   7.《C++ 设计新思维》, "Modern C++ Design" by Andrei Alexandrescu.
   8.《Effective STL》by Scott Meyers.


期末作业。各组任选一题。评分将视选题困难度而有所调整。
评分根据:选题困难度、程式可执行度、程式手法优劣、目标达成度、
                    上台演出情况、书面报告。
1.  改善 SGI STL memory pool 的效率。其优缺点可从「 2002/09 池内春秋
       memory pool 的设计哲学和无痛运用」一文中的执行步骤看出。缴交的作业必须也能   执行相同(或类似)的步骤,并以相同(或类似)的画面显示出你的改善效果。

2. 任选 deque, rb-tree, hashtable, sort, copy, next_permutation, prev_permutation ...等在复杂度上具有代表性的容器或演算法,以交谈方式逐一获得输入数据,再以图形方式展现其内容之逐一变化。(展现的萤幕图形,应类似书中的图)。

有同学询问是否可使用 Java 完成绘图部分,我的回答是你可以使用任何语言、任何工具来辅助绘图,只要最终可形成一个独立的可执行档(.exe)。但若你选择 C++ 以外的语言,如何让你的绘图组件和 C++ STL 沟通呢?毕竟你需要从 STL 取得每次交谈式输入数据後的容器或演算法的内容变化。

另有同学询问可否使用 SGI (GNU C++) 以外的版本完成上述题目。我的回答是 OK。但是第一道题目中所说的 memory pool,只存在於 SGI(或其衍化)版本中。就我所知 STLPort  http://www.stlport.org/ 是一套以 SGI 版为基础的高可携性 STL,应该可以轻松移植到众多主流编译器上。

■第1周:02/18(第一次上课
1 课程介绍,游戏规则,书籍评介,期末作业题目(未定),助教协助购书
2 GP (Generic Programming) and STL overview
// 程式一
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int intcmp(const void* a1, const void* b1)
{
  const int* a = (const int*)a1;
  const int* b = (const int*)b1;

  if (*a < *b)  return -1;
  if (*a == *b) return 0;
  if (*a > *b)  return 1;
}

void main()
{
  int ilist[5]={8,20,7,98,105};
  int  i, ret, key=7;

    printf("%d \n", sizeof(ilist[0]));    // 4
    qsort(&ilist, 5, sizeof(ilist[0]), intcmp);
    for (i=0; i<5; i++)
         printf("%d \n", ilist[i]);
    if (0==bsearch(&key, &ilist, 5, sizeof(ilist[0]), intcmp))
        printf("not found\n");
    else
        printf("find\n");
}

// 程式二
// headers 应采用新的规格
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

// 一个用以列印的 functor

template<typename T>
class printElem
{
public:
   void operator()(const T& i)
   {  cout << i << ' ';  }
};

int main()
{
  int ia[10] = {2,6,9,14,49,70,38,90,71,28};

  // 使用 vector
  vector<int>  vi(&ia[0], &ia[10]);
  vi.push_back(38);

  cout << vi.size() << endl;      // 11
  cout << vi.capacity() << endl;  // 20(每次成长两倍)
  for(int i=0; i<vi.size(); ++i)
      cout << vi[i] << ' ';

  // 使用 iterators
  vector<int>::iterator  ite1 = find(vi.begin(), vi.end(), 49);
  vector<int>::iterator  ite2 = find(vi.begin(), vi.end(), 90);

  cout << *ite1 << endl;  // 49
  cout << *ite2 << endl;  // 90

  cout << "jjhou" << int(5) << endl; // 暂时物件

  sort(vi.begin(), vi.end());

  for_each(vi.begin(), vi.end(), printElem<int>());
}
■第2周:02/25
《STL源码剖析》书到。  峰予 7 折优惠。   
Console 模式中使用C/C++ 编译器
继续练习 STL 实例
各种 STL containers 和 STL algorithms(以及其他组件)的运用,是很有趣的。
同学应该自己动手试试。

这里附上一个 .ppt,对本次课中许多同学所疑惑的 functor和 for_each() 或许有帮助。

同学发问 :

Dear teacher:
老师,我想把有关for each第三个叁数的问题再延伸一下,虽然老师您今天说使用functor比function pointer的overhead稍稍大了一点,那为什麽我们不大量改用fuction pointer,而仍旧使用functor为主(我记得老师今天说过,在STL里面常使用functor),fuctor是有存在什麽过人的优点,让我们非使用fuctor不可呢?还麻烦老师在下周上课时,能为我解答一二。


Sent: Thursday, February 26, 2004 6:35 PM
Subject: 侯老师您好
最近玩了一下STL,
发现algorithm当中,
random_shuffle很奇怪耶,
写好的程式,
若每次的array初值都是一样,
经过它的乱序排列,
每次执行程式的结果,结果都一样?

int main(int argc, char* argv[])
{
cout << "Please Input Range Number N(i.e.,1~N):";
int N;
cin >> N;
cout << endl;

vector<int> NUMBER(N);
cout << "Original Order:" <<endl;
for(int i=0;i<N;i++)
{
NUMBER[i]=i+1;
cout << NUMBER[i] << ",";
}

random_shuffle(NUMBER.begin(),NUMBER.end());

cout << endl << "After Shuffle Order:" << endl;
for(int i=0;i<N;i++)
{
cout << NUMBER[i] << ",";
}
}


Sent: Thursday, February 26, 2004 1:06 PM
Subject: about function pointer...please.
侯老师 您好 :
有个 function pointer 的问题想请教您.
我的目的是要用一个函式指标阵列去索引到各个函式, 各函式的叁数型别及数量都不尽相同, 我试了简略符号 (Ellipses) ,可是这样宣告的话 ,编译时就有错. (我的编译器是 Borland C++ Builder 4.0 ) 您可以拨冗帮我看看吗 ? 谢谢.
程式码如後,错误讯息如附件.
祝教安

#pragma hdrstop
#include <condefs.h>
#include <stdlib.h>
int f1(int);
int f2(int,int);
int f3(int,int,char);
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
int (*ftn[3])(int,...)={f1,f2,f3};
return 0;
}

int f1(int i)
{
return i;
}

int f2(int i,int j)
{
return i+j;
}

int f3(int i,int j,char *a)
{
int ia=atoi(a);
return i*j*ia;
}

■第3周:03/03
书续到。  峰予 7 折优惠。   
继续练习 STL 实例
本周复习 Class Templates

这个  .ppt 是本课程讲义

Q1:
const Complex operator+(const Complex& x) {
    return Complex<T>(*this) += x;          //是什麽意思
}
A1: 以 *this 为初值产生一个暂时物件,将该暂时物件加上 x,传回。

Q2: for_each() 的叁数为什麽采用pass by value?
A2: 我认为 STL 设计者的一个可能想法是:传入的 first iterator 在 for_each() 中有所改动,因此不希望影响呼叫端。传入的 functor也可能有所改动(因为其 operator()被呼叫後难保不会改变其state),不希望影响呼叫端。至於 last,的确不会被改动。

Q3: binary_search() 为什麽可以接受 forward_iterator?
A3: 从《STL源码剖析》p379 -->p375可知,binary_search() 使用 lower_bound(),後者有两个版本,一是 forword iterator版本,较慢。一是random access iterator 版本,较快。编译器会根据程式实际所给的 iterator type 决定呼叫哪一个版本。

Q4:
const C obj1;
C obj2;
C obj3 = obj1 + obj2; 是否需要一个 member function operator+ const { ... } ?
A4: 是的。如果只有 member function operator+ { ...},编译不过。

Q5: 请再次解释 overloading

■第4周:03/10
本周复习 Function Templates
本周复习 Operator overloading
.ppt 本课程讲义
另例
■第5周:03/17
.ppt 本课程讲义
本周复习 
static members, 
new expression and operator new, 
delete expression and operator delete, 
array new, 
memory pool concept
本周主题:STL Allocator
更多资讯 2002/09 池内春秋
■第6周:03/24
.ppt 本课程讲义
本周主题:STL Allocator
■第7周:03/31
.ppt 本课程讲义
本周主题:Iterator  Tratis
■第8周:04/07
.ppt 本课程讲义
本周主题:
(1) Type  Tratis
(2) STL Lite
yz-allocator.h
yz-list.h
yz-algorithm.h
yz-functional.h
yz-iterator.h
yz-main.cpp
同学很用心地回去查了字典,给了我一封信如下。我很开心同学的态度。
昨天提到了尸位素餐这个成语,所以我回家後便查了一下典故,希望能跟老师分享。

尸音史,是古代祭礼中的一个代表神像端坐看而不须要做任何动作的人。
“书经”有句道:“太康尸位””尸位就是源出於此,用来比喻一个有职位而
没有工作做的人,正如祭礼中的尸,只坐在位上,不必做任何动作一样。
“素餐”也是出於诗经:“彼君子兮,不素餐兮。”後人於是用“素餐”来比喻
无功食禄的人。把“尸位”和“素餐”两者连合成为一句成语,应该说是
出於“汉书”,因为该书的“朱云传”裹:“今朝廷大臣,上不能匡主,
下亡以益民,皆尸位素餐。”整句成语的意思,也是和上述的尸位和素餐相同。
这样说,我们要研究成语的出处,对这句成语分合的出处,也应该详细知道。

一般机关、社团、商店的冗员,凭看人事或其他特殊的关系,只知道每月按期
领取薪金,每日吃喝闲坐,而不做任何工作,这种人都可以说是“尸位素餐”。
此外,一般工作能力很差的人,虽然已经尽了自己的能力服务,但事情总是做不好,
毫无成积可言,这种人能够保持职位,不是靠自己的本领,而是藉着特殊关系,
因此也可以说“尸位素餐”。
■第9周:04/14(期中考周。停课一次。本课程无期中考
■第10周:04/21
vector, list, deque
■第11周:04/28
set, map, hashtable
.ppt 本课程讲义
■第12周:05/05
hashtable, iostream iterator
.ppt 本课程讲义
分组名单
第 1 组
901436 简汶翰
901315 陈志仁
902205 梁宏达
902229 李宗益
902253 廖世杰
902254 吴俊纬
第 2 组
902220 张皓杰
902255 田益维
902236 张耀宗
902249 董锦宜
902201 陈树松
第 3 组
882356 李建辉
892632 方鹤
912323 蔡勋任
912332 简廷因
912343 张恒瑞
912356 吴梵诚
第 4 组
902315 刘致光
902323 蔡佩辰
902331 陈重民
902332 古镇宇
902335 王仁晖
902359 陈劲凡
第 5 组
902209 徐士卜
902208 陈宗邦
902207 陈伯符
902219 洪圣哲
902231 黄威晟
902240 林益平
第 6 组
902228 杨贵麟
902334 王佩蓁
902342 刘芳伶
902349 徐悦芝
902350 林彦伯
902351 李素玫
第 7 组
902260 麦云峰
902310 朱国宏
902317 魏宇泽
902340 李昌达
902360 何家豪
第 8 组
902257 薛博元
902234 彭玉池
902237 董信宗
902222 姜兆刚
902244 何沛宇
902233 于世庆
第 9 组(名单重复,取消)
902248 凌钰城
902251 周彦如
902259 郑孟璇
902349 徐悦芝
第 10 组
892212 刘    
892229 陈奕超
892233 江政哲
892234 林采盈
892359 梁维修 
第 11 组
882348 陈坤琦      
882324 叶天翔       
892314 杨  桦       
892350 王顺英       
892340 罗邦翔 
912340 郑杰仁
第 12 组
902241 蔡  芸
902248 凌钰城
902251 周彦如
902259 郑孟璇
第 13 组
912327 洪鹏杰
912309 陈彦如
912349 张家豪
第 14 组
902336 方禀淳
902305 蓝伟铭
902328 李  升
902320 锺承佑
■第13周:05/12
iostream iterator, adapter
■第14周:05/19
memory allocation and design patterns in std::String
.ppt 本课程讲义
■第15周:05/26
memory allocation and design patterns in std::String
----- Original Message -----
Subject: 来自一个旁听者的感谢
> 老师:
>
> 您好。我是一个憧憬着严谨的逻辑世界,却始终未能在编
> 程领域登堂入室的人。这学期因缘具足,来上了您在元智
> 大学开的 STL与泛型程式设计课。感谢老师在众多修课学
> 生之外,慷慨地接受外来的旁听者。课上到後来,我习惯
> 了坐在最前面,一方面看投影画面较轻松,一方面也容易
> 向老师请益。只是常常发问,影响了老师上课的进度,也
> 有损其他正式修课同学的权益,实在不好意思,只好在此
> 向老师以及同学们表示歉意。
>
> 如果没有老师的引领,我大概只是安於做一个 STL的使用
> 者,永远不会去接触它的源码,一窥其设计的奥秘。然而,
> 来听老师的课,除了技术的提升,更大的启示来自於亲炙
> 老师,从您身上感受到的做人与求学的态度。原来,即使
> 活在这麽一个浮薄的时代,一个人仍然可以勤勉恳切,一
> 砖一瓦的搭建起学问的殿堂,踏踏实实地走出自己人生的
> 康庄大道。
>
> 我所学到的一些技术也许有过时的一天,但是我诚愿将这
> 种老实做人的精神永远放在心上。
>
> 谨向老师深深一鞠躬。
>
> 学生 □□□ 敬上
Hi, □□ :

课程中我便注意到您,总是坐在第一排或第二排,神态认真专注。

在这麽些年的课程当中,旁听的同学带给我最大的欣慰。因为你们
总是那麽专注、珍惜、用功。

虽然你们觉得是我给了你们 something,是我帮助了你们。但我要说,
在授课过程中,这样(专注、珍惜、用功)的学生对我也是非常重要,
意义非凡。

谢谢你们。

我个人谈不上在「学问的殿堂」上有什麽成绩。「勤勉恳切踏踏实实」倒的确是
真实的写照。如果在这个形象上我对同学带来了某种正面的影响,我非常开心 :)

> 只是常常发问,影响了老师上课的进度,也有损其他正式修课
同学的权益,实在不好意思,只好在此向老师以及同学们表示歉意。

我的课程永远欢迎发问。这会使上课气氛活泼,带动其他同学的勇气。
发问对课程的良性发展有帮助 :) 你有功於本课程 :)

-- jjhou

■第16周:06/02(缴交期末作业并上台报告
■第17周:06/09(缴交期末作业并上台报告
■第18周:06/16(期末考周。本课程无期末考