rctrace.cpp

来自「Think in C++文中代码实现」· C++ 代码 · 共 157 行

CPP
157
字号
// File from page 440 in "Thinking in C++" by Bruce Eckel
//////////////////////////////////////////////////
// From the compressed package ECKELT02.ZIP 4/11/95
// (Original ECKELT01.ZIP dated 2/21/95)
// Copyright (c) Bruce Eckel, 1995 
// Source code file from the book "Thinking in C++", 
// Prentice Hall, 1995, ISBN: 0-13-917709-4
// All rights reserved EXCEPT as allowed by the following 
// statements: You may freely use this file for your own 
// work, including modifications and distribution in 
// executable form only. You may copy and distribute this 
// file, as long as it is only distributed in the complete 
// (compressed) package with the other files from this 
// book and you do not remove this copyright and notice. 
// You may not distribute modified versions of the source 
// code in this package. This package may be freely placed 
// on bulletin boards, internet nodes, shareware disks and 
// product vendor disks. You may not use this file in 
// printed media without the express permission of the 
// author. Bruce Eckel makes no 
// representation about the suitability of this software 
// for any purpose. It is provided "as is" without express 
// or implied warranty of any kind. The entire risk as to 
// the quality and performance of the software is with 
// you. Should the software prove defective, you assume 
// the cost of all necessary servicing, repair, or 
// correction. 
// If you think you've found an error, please 
// email all modified files with loudly commented changes 
// to: eckel@aol.com (please use the same 
// address for non-code errors found in the book).
//////////////////////////////////////////////////

//: RCTRACE.CPP -- REFCOUNT.CPP w/ trace info
#include <string.h>
#include <fstream.h>
#include <assert.h>
ofstream out("rctrace.out");

class counted {
  class memblock {
    enum { size = 100 };
    char c[size];
    int refcount;
    static int blockcount;
    int blocknum;
  public:
    memblock() {
      memset(c, 1, size);
      refcount = 1;
      blocknum = blockcount++;
    }
    memblock(const memblock& rv) {
      memcpy(c, rv.c, size);
      refcount = 1;
      blocknum = blockcount++;
      print("copied block");
      out << endl;
      rv.print("from block");
    }
    ~memblock() {
      out << "\tdestroying block "
          << blocknum << endl;
    }
    void print(const char* msg = "") const {
      if(*msg) out << msg << ", ";
      out << "blocknum:" << blocknum;
      out << ", refcount:" << refcount;
    }
    void attach() { ++refcount; }
    void detach() {
      assert(refcount != 0);
      // Destroy object if no one is using it:
      if(--refcount == 0) delete this;
    }
    int count() const { return refcount; }
    void set(char x) { memset(c, x, size); }
    // Conditionally copy this memblock.
    // Call before modifying the block; assign
    // resulting pointer to your block;
    memblock* unalias() {
      // Don't duplicate if not aliased:
      if(refcount == 1) return this;
      --refcount;
      // Use copy-constructor to duplicate:
      return new memblock(*this);
    }
  } * block;
  enum { sz = 30 };
  char id[sz];
public:
  counted(const char* ID = "tmp") {
    block = new memblock; // Sneak preview
    strncpy(id, ID, sz);
  }
  counted(const counted& rv) {
    block = rv.block; // Pointer assignment
    block->attach();
    strncpy(id, rv.id, sz);
    strncat(id, " copy", sz - strlen(id));
  }
  void unalias() { block = block->unalias(); }
  void addname(const char* nm) {
    strncat(id, nm, sz - strlen(id));
  }
  counted& operator=(const counted& rv) {
    print("inside operator=\n\t");
    if(&rv == this) {
      out << "self-assignment" << endl;
      return *this;
    }
    // Clean up what you're using first:
    block->detach();
    block = rv.block; // Like copy-constructor
    block->attach();
    return *this;
  }
  // Decrement refcount, conditionally destroy
  ~counted() {
    out << "preparing to destroy: " << id
        << endl << "\tdecrementing refcount ";
    block->print();
    out << endl;
    block->detach();
  }
  // Copy-on-write:
  void write(char value) {
    unalias();
    block->set(value);
  }
  void print(const char* msg = "") {
    if(*msg) out << msg << " ";
    out << "object " << id << ": ";
    block->print();
    out << endl;
  }
};

int counted::memblock::blockcount = 0;

main() {
  counted A("A"), B("B");
  counted C(A);
  C.addname(" (C) ");
  A.print();
  B.print();
  C.print();
  B = A;
  A.print("after assignment\n\t");
  B.print();
  out << "Assigning C = C" << endl;
  C = C;
  C.print("calling C.write('x')\n\t");
  C.write('x');
  out << endl << "exiting main()" << endl;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?