📄 refcounttrace.cpp
字号:
//: C12:RefcountTrace.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 1999
// Copyright notice in Copyright.txt
// Refcount.cpp w/ trace info
#include "../require.h"
#include <cstring>
#include <fstream>
using namespace std;
ofstream out("rctrace.out");
class Counted {
class MemBlock {
static const int 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() {
require(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;
static const int sz = 30;
char ident[sz];
public:
Counted(const char* id = "tmp") {
block = new MemBlock; // Sneak preview
strncpy(ident, id, sz);
}
Counted(const Counted& rv) {
block = rv.block; // Pointer assignment
block->attach();
strncpy(ident, rv.ident, sz);
strncat(ident, " copy", sz - strlen(ident));
}
void unalias() { block = block->unalias(); }
void addname(const char* nm) {
strncat(ident, nm, sz - strlen(ident));
}
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: " << ident
<< "\n\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 " << ident << ": ";
block->print();
out << endl;
}
};
int Counted::MemBlock::blockcount = 0;
int 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 << "\n exiting main()" << endl;
} ///:~
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -