C++编程思想 第1卷 第9章 内联函数 带内联函数的Stash和Stack

本文介绍了一个C++程序中用于管理动态内存的Stash和Stack类。Stash类通过内联函数提高了性能,Stack类则完全由内联函数构成。文章还提供了测试程序,验证了这些类的功能。

引入内联函数,可以把Stash和Stack类变得更有效

 

//: C09:Stash4.h
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Inline functions
#ifndef STASH4_H
#define STASH4_H
#include "../require.h"

class Stash {
  int size;      // Size of each space
  int quantity;  // Number of storage spaces
  int next;      // Next empty space
  // Dynamically allocated array of bytes:
  unsigned char* storage;
  void inflate(int increase);
public:
  Stash(int sz) : size(sz), quantity(0),
    next(0), storage(0) {}
  Stash(int sz, int initQuantity) : size(sz), 
    quantity(0), next(0), storage(0) { 
    inflate(initQuantity); 
  }
  Stash::~Stash() {
    if(storage != 0) 
      delete []storage;
  }
  int add(void* element);
  void* fetch(int index) const {
    require(0 <= index, "Stash::fetch (-)index");
    if(index >= next)
      return 0; // To indicate the end
    // Produce pointer to desired element:
    return &(storage[index * size]);
  }
  int count() const { return next; }
};
#endif // STASH4_H ///:~

 

小函数作为内联函数工作是理想的,要注意,两个最大的函数仍旧保留非
内联函数,因为要是把它们作为内联使用的话,很可能性能上得不到改善
 

//: C09:Stash4.cpp {O}
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
#include "Stash4.h"
#include <iostream>
#include <cassert>
using namespace std;
const int increment = 100;

int Stash::add(void* element) {
  if(next >= quantity) // Enough space left?
    inflate(increment);
  // Copy element into storage,
  // starting at next empty space:
  int startBytes = next * size;
  unsigned char* e = (unsigned char*)element;
  for(int i = 0; i < size; i++)
    storage[startBytes + i] = e[i];
  next++;
  return(next - 1); // Index number
}

void Stash::inflate(int increase) {
  assert(increase >= 0);
  if(increase == 0) return;
  int newQuantity = quantity + increase;
  int newBytes = newQuantity * size;
  int oldBytes = quantity * size;
  unsigned char* b = new unsigned char[newBytes];
  for(int i = 0; i < oldBytes; i++)
    b[i] = storage[i]; // Copy old to new
  delete [](storage); // Release old storage
  storage = b; // Point to new memory
  quantity = newQuantity; // Adjust the size
} ///:~

 

测试程序表面可以正常运行

 

//: C09:Stash4Test.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
//{L} Stash4
#include "Stash4.h"
#include "../require.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main() {
  Stash intStash(sizeof(int));
  for(int i = 0; i < 100; i++)
    intStash.add(&i);
  for(int j = 0; j < intStash.count(); j++)
    cout << "intStash.fetch(" << j << ") = "
         << *(int*)intStash.fetch(j)
         << endl;
  const int bufsize = 80;
  Stash stringStash(sizeof(char) * bufsize, 100);
  ifstream in("Stash4Test.cpp");
  assure(in, "Stash4Test.cpp");
  string line;
  while(getline(in, line))
    stringStash.add((char*)line.c_str());
  int k = 0;
  char* cp;
  while((cp = (char*)stringStash.fetch(k++))!=0)
    cout << "stringStash.fetch(" << k << ") = "
         << cp << endl;
  getchar();
} ///:~

 

把Stash4Test.cpp 放到 工程目录

输出 正序输出
intStash.fetch(0) = 0
intStash.fetch(1) = 1
intStash.fetch(2) = 2
intStash.fetch(3) = 3
intStash.fetch(4) = 4
intStash.fetch(5) = 5
intStash.fetch(6) = 6
intStash.fetch(7) = 7
intStash.fetch(8) = 8
intStash.fetch(9) = 9
intStash.fetch(10) = 10
intStash.fetch(11) = 11
intStash.fetch(12) = 12
intStash.fetch(13) = 13
intStash.fetch(14) = 14
intStash.fetch(15) = 15
intStash.fetch(16) = 16
intStash.fetch(17) = 17
intStash.fetch(18) = 18
intStash.fetch(19) = 19
intStash.fetch(20) = 20
intStash.fetch(21) = 21
intStash.fetch(22) = 22
intStash.fetch(23) = 23
intStash.fetch(24) = 24
intStash.fetch(25) = 25
intStash.fetch(26) = 26
intStash.fetch(27) = 27
intStash.fetch(28) = 28
intStash.fetch(29) = 29
intStash.fetch(30) = 30
intStash.fetch(31) = 31
intStash.fetch(32) = 32
intStash.fetch(33) = 33
intStash.fetch(34) = 34
intStash.fetch(35) = 35
intStash.fetch(36) = 36
intStash.fetch(37) = 37
intStash.fetch(38) = 38
intStash.fetch(39) = 39
intStash.fetch(40) = 40
intStash.fetch(41) = 41
intStash.fetch(42) = 42
intStash.fetch(43) = 43
intStash.fetch(44) = 44
intStash.fetch(45) = 45
intStash.fetch(46) = 46
intStash.fetch(47) = 47
intStash.fetch(48) = 48
intStash.fetch(49) = 49
intStash.fetch(50) = 50
intStash.fetch(51) = 51
intStash.fetch(52) = 52
intStash.fetch(53) = 53
intStash.fetch(54) = 54
intStash.fetch(55) = 55
intStash.fetch(56) = 56
intStash.fetch(57) = 57
intStash.fetch(58) = 58
intStash.fetch(59) = 59
intStash.fetch(60) = 60
intStash.fetch(61) = 61
intStash.fetch(62) = 62
intStash.fetch(63) = 63
intStash.fetch(64) = 64
intStash.fetch(65) = 65
intStash.fetch(66) = 66
intStash.fetch(67) = 67
intStash.fetch(68) = 68
intStash.fetch(69) = 69
intStash.fetch(70) = 70
intStash.fetch(71) = 71
intStash.fetch(72) = 72
intStash.fetch(73) = 73
intStash.fetch(74) = 74
intStash.fetch(75) = 75
intStash.fetch(76) = 76
intStash.fetch(77) = 77
intStash.fetch(78) = 78
intStash.fetch(79) = 79
intStash.fetch(80) = 80
intStash.fetch(81) = 81
intStash.fetch(82) = 82
intStash.fetch(83) = 83
intStash.fetch(84) = 84
intStash.fetch(85) = 85
intStash.fetch(86) = 86
intStash.fetch(87) = 87
intStash.fetch(88) = 88
intStash.fetch(89) = 89
intStash.fetch(90) = 90
intStash.fetch(91) = 91
intStash.fetch(92) = 92
intStash.fetch(93) = 93
intStash.fetch(94) = 94
intStash.fetch(95) = 95
intStash.fetch(96) = 96
intStash.fetch(97) = 97
intStash.fetch(98) = 98
intStash.fetch(99) = 99
stringStash.fetch(1) = //: C09:Stash4Test.cpp
stringStash.fetch(2) = // From Thinking in C++, 2nd Edition
stringStash.fetch(3) = // Available at http://www.BruceEckel.com
stringStash.fetch(4) = // (c) Bruce Eckel 2000
stringStash.fetch(5) = // Copyright notice in Copyright.txt
stringStash.fetch(6) = //{L} Stash4
stringStash.fetch(7) = #include "Stash4.h"
stringStash.fetch(8) = #include "../require.h"
stringStash.fetch(9) = #include <fstream>
stringStash.fetch(10) = #include <iostream>
stringStash.fetch(11) = #include <string>
stringStash.fetch(12) = using namespace std;
stringStash.fetch(13) =
stringStash.fetch(14) = int main() {
stringStash.fetch(15) =   Stash intStash(sizeof(int));
stringStash.fetch(16) =   for(int i = 0; i < 100; i++)
stringStash.fetch(17) =     intStash.add(&i);
stringStash.fetch(18) =   for(int j = 0; j < intStash.count(); j++)
stringStash.fetch(19) =     cout << "intStash.fetch(" << j << ") = "
stringStash.fetch(20) =          << *(int*)intStash.fetch(j)
stringStash.fetch(21) =          << endl;
stringStash.fetch(22) =   const int bufsize = 80;
stringStash.fetch(23) =   Stash stringStash(sizeof(char) * bufsize, 100);
stringStash.fetch(24) =   ifstream in("Stash4Test.cpp");
stringStash.fetch(25) =   assure(in, "Stash4Test.cpp");
stringStash.fetch(26) =   string line;
stringStash.fetch(27) =   while(getline(in, line))
stringStash.fetch(28) =     stringStash.add((char*)line.c_str());
stringStash.fetch(29) =   int k = 0;
stringStash.fetch(30) =   char* cp;
stringStash.fetch(31) =   while((cp = (char*)stringStash.fetch(k++))!=0)
stringStash.fetch(32) =     cout << "stringStash.fetch(" << k << ") = "
stringStash.fetch(33) =          << cp << endl;
stringStash.fetch(34) = } ///:~

Stack类更好地使用了内联函数

//: C09:Stack4.h
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// With inlines
#ifndef STACK4_H
#define STACK4_H
#include "../require.h"

class Stack {
  struct Link {
    void* data;
    Link* next;
    Link(void* dat, Link* nxt): 
      data(dat), next(nxt) {}
  }* head;
public:
  Stack() : head(0) {}
  ~Stack() {
    require(head == 0, "Stack not empty");
  }
  void push(void* dat) {
    head = new Link(dat, head);
  }
  void* peek() const { 
    return head ? head->data : 0;
  }
  void* pop() {
    if(head == 0) return 0;
    void* result = head->data;
    Link* oldHead = head;
    head = head->next;
    delete oldHead;
    return result;
  }
};
#endif // STACK4_H ///:~

 

Link析构函数在前面的Stack版本是以空的形式出现的,这里删除了

多数内联函数十分精细和明显,特别对于Link如此

如果所有的函数都是内联函数,那么使用库就会变得相当简单,因为不需要
进行库连接,注意没有Stack4.cpp

 

//: C09:Stack4Test.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
//{T} Stack4Test.cpp
#include "Stack4.h"
#include "../require.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char* argv[]) {
  requireArgs(argc, 1); // File name is argument
  ifstream in(argv[1]);
  assure(in, argv[1]);
  Stack textlines;
  string line;
  // Read file and store lines in the stack:
  while(getline(in, line))
    textlines.push(new string(line));
  // Pop the lines from the stack and print them:
  string* s;
  while((s = (string*)textlines.pop()) != 0) {
    cout << *s << endl;
    delete s; 
  }
  getchar();
} ///:~

 

结果就是按行的逆序输出
有时创建的类都是内联成员函数时,可以把整个类放到头文件中,在程序
开发中,这是有益的,尽管编译时会花费更多的编译时间


输出
命令行参数 Stack4Test.cpp 的绝对路径,字符串要加引号,里面有斜括号
输出
} ///:~
  getchar();
  }
    delete s;
    cout << *s << endl;
  while((s = (string*)textlines.pop()) != 0) {
  string* s;
  // Pop the lines from the stack and print them:
    textlines.push(new string(line));
  while(getline(in, line))
  // Read file and store lines in the stack:
  string line;
  Stack textlines;
  assure(in, argv[1]);
  ifstream in(argv[1]);
  requireArgs(argc, 1); // File name is argument
int main(int argc, char* argv[]) {

using namespace std;
#include <string>
#include <iostream>
#include <fstream>
#include "../require.h"
#include "Stack4.h"
//{T} Stack4Test.cpp
// Copyright notice in Copyright.txt
// (c) Bruce Eckel 2000
// Available at http://www.BruceEckel.com
// From Thinking in C++, 2nd Edition
//: C09:Stack4Test.cpp
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值