卖个关子,先谈“反求诸己”,文章的最后再谈“世界末日”、为什么世界末日会“迟到”。

“反求诸己”是一件让人乐此不疲但又烦躁不堪的事情。思考人类终极命运这种问题难道不是令人沮丧的么?人固有一死,早死晚死都得死;尽管我们一再强调,有些尸体是重于泰山的,但“你会死”这种陈述终归不是什么好话。打情骂俏、调戏人的和反调戏的除外。可是,即便是这样,我们还是对生命的爱与执着这种“反熵(anti-entropy)”的事情乐此不疲,不是么?就好像,尽管李安大师《少年派的奇幻之旅》血腥重口版很可能是事实,我们仍然选择相信浪漫励志版,不是么?

这篇文章是我个人的年终总结。

这些年来每一年我都至少会写一篇文章,反思我这一年又做了哪些特二的事情,下一年还想做哪些不那么二的事情。

也许更早的时候我也写过不少东西,只不过都删除掉了,没有存档。看着这些个人总结,我突然特别好奇:大学四年的不同时期,我都在想些什么?

首先,生活一直在别处,我似乎不是那么的开心。

这是可以理解的,一来要直面自己做得不对的事情,二来这些文字大多落笔于寒冬,而寒冬本身就是令人很绝望的存在。除夕辞旧迎新其实是有象征意味的,只有将过往的积郁都扫除掉,打上一剂名叫希望的鸡血,才能勇敢地重装上阵。所以当我回味百里屠苏“屠绝鬼气,苏醒人魂”的时候,内心难免会感动不已。

值得注意的是,“生活在别处”有别于“逃离”,“逃离”是一种可悲的心态,你总以为“如果我在其他的地方,我会活得更好”,但是,你我都知道,境由心生,你在哪和你活的好不好无关丝毫。“生活在别处”应该是一种直面、自嘲,更重要的是,是一种向往,对人类内心深处亘古不变的真理的向往,这些向往是什么?是爱、怜悯、自豪、同情、恐惧、牺牲和荣耀。没有了这些向往,我们追求的不是爱,而是情欲;我们的苦难里没有任何人失去真正有价值的东西;我们的胜利里没有任何让我们热血沸腾的奇迹;最为糟糕的是,没有了怜悯和同情,我们的哀伤很可能是无病呻吟,不值一提;那些让心儿为之颤抖的,不是灵魂,而是内分泌。

其次,我一直在抱怨自己读书太少。

我逐渐患上了一种奇特的拖延症。多年前,我成为了Sir Winston Churchill的“I have only one purpose, the destruction of Hitler, and my life is much simplified thereby.”这句话的脑残粉。从那以后,每当我打算专心做一件事情的时候,其他的所有都会被抛诸脑后。可惜的是,这些事都不是一天两天能够做完的,而我记性又不大好,这就导致,每当这些事情完成的时候,那些被抛诸脑后的事情也就已然类似于抛猪脑后了。读书少是表现之一,所以,多年来的这些总结都在反复提醒自己多读多写。

另外一个表现是

隔壁的Bryan老兄每次寒暄 how’s it going? 的时候他也许会感到很奇怪,为啥对面这小兄弟怎么连招呼都打得一愣一愣的。而对面的小兄弟我,每次都本能地将其反应成“最近过得怎样?”,然后进一步考虑,该如何回答这个”特殊疑问句“,总不能每次都说”Not bad”吧;但实际的情况是,还真没有什么好说的,而且这句话本来就是“how are you?”类型的句子,是不需要认真回答的,一个hi/hello/hey 足矣。

每次父母找我聊天,问东问西,总以为我在国外的生活应该是丰富多彩的,如果我问题回答地不够给力,他们就会反复感叹类似于好桑心啊好桑心,都没有共同语言啊,老了啦,之类的感叹。这让我十分汗颜,不是我不跟你们讲,而是我真没有什么好讲的,我不是在看书就是在刷微博就是在吃东西就是在去吃东西的路上就是梦里面吃东西,但这些事务并不是什么可以可以诉说甚至引以为豪的事情。大家往往以旅游、靓照、趴踢、大餐为乐为豪,是,确实很欢乐,我也超级喜欢,但是,我只是觉得,这些对我来说不重要,至少对于现在的我说不重要。

我也知道我眼界不甚开阔,很狭隘。雅礼是一所非常好的学校,我在这里遇到了无数精英,这群精英不是来自Ivy就是来自Stanford, Berkeley, 就是Oxford, Cambridge, 就是清北浙上交复旦等大牛校的帅哥靓女。是,他们寒暑假可以上到青藏高原下到日本海沟,南到极地游轮抢拍鲸鱼北到阿拉斯加入住爱斯基摩的雪屋。是,他们博闻广志风流倜傥,有太多太多值得我学习的地方,我对他们、对这个世界敬畏有加。但这丝毫不妨碍我作为国关人的自豪与自嘲,但这丝毫不妨碍我这辈子对家乡的思念和出逃,但这丝毫不妨碍我对我所热爱的选择的偏执与傲娇。

我从来就不曾想过出国是一件舒舒服服安享幸福生活的事情,过去没有,现在没有,将来也不会有!请不要和我谈生活,我没有生活。请不要问我后不后悔,我只怕我不能够爱得深切,我只怕我不能够屁颠屁颠地、但却矢志不渝地自鸣得意地自命不凡地把我自己选择的路,充盈地,走下去。


如果自己不定义constructor,C++会默认使用空的constructor。但是如果自己声明了,就一定要把定义写出来。


Reuse and recycle. Maintain a free list a pool of currently unused objects and reuse rather than recreate when possible.


How to measure run time of a program?

Clocks advance in discrete clicks called jiffies. A jiffy on the Zoo linux machines is one millisecond (0.001 seconds) long.

the first run of a program is likely to be slower than subsequent runs because of caching.

class members are private by default.

if(!in) {...}

to test if an istream object in is open for reading. Here, the istream object is coerced to a bool because operator bool() is defined inside the streams package.


operator⊕ overload

a⊕b can be ambiguous

  • Global function: operator⊕(a, b).
  • Member function: a.operator⊕(b).

It could mean either, and the compiler sees if either one matches. If both match, it reports an ambiguity.

We use a global form of operator<< because the left hand operator is of predefined type ostream, and we can’t add member functions to that class.

++, –

  1. prefix unary operators

  2. class member: operator++()

  3. global: operator++(ClassA a)

  4. postfix unary operators

They must be like

  • class member: operator++(int)
  • global: operator++(ClassA a, int)

Here int is dummy.


两种定义类的cast的方式 cast A to B

class A {};
class B{
    public:
    B(A& a) {
        cout << "constructor cast called" << endl;
    }
};

conversion function cast

class B {};
class A {
    public:
    operator B() {
        cout << "operator B cast called" << endl;
        return *new B;
    } 
};

注意没有返回类型,讲述自己怎么被cast成其他类


Polymorphism

class B     { public: int f(); ... };
class U : B { int f(); ... };
class V : B { int f(); ... };

B* bp can point to B, U, and V, but bp->f() always refers to B::f()

Solution: Polymorphic derivation

   class B     { public: virtual int f(); ... };
   class U : B { virtual int f(); ... };
   class V : B { virtual int f(); ... };
   B* bp;

A virtual function is dispatched at run time to the class of the actual object.

  • bp->f() refers to U::f() if bp points to a U.
  • bp->f() refers to V::f() if bp points to a V.
  • bp->f() refers to B::f() if bp points to a B.

Here, the type refers to the allocation type.

其实,只有基类加virtual都是可以的


Calling constructors implicitly

MyClass b;
MyClass b(4);
new MyClass(4);

Calling constructors explicitly

MyClass(4);
throw Fatal("Error message"); 

A pure virtual function is sometimes called a promise. Instances of B are never created and B::f() does not exist. It tells the compiler that a construct like bp->f() is legal. The compiler requires every derived class to contain a method f().

An abstract class is a class with one or more pure virtual functions. An abstract class cannot be instantiated. It can only be used as the base for another class. The destructor can never be a pure virtual function but will generally be virtual.

A pure abstract class is one where all member functions are pure virtual (except for the destructor) and there are no data members, Pure abstract classes define an interface `a la Java. An interface allows user-supplied code to integrate into a large system.


A global function is one that takes zero or more explicit arguments. Example: f(a, b) has two explicit arguments a and b.

A member function is one that takes an implicit argument along with zero or more explicit arguments. Example: c.g(a, b) has two explicit arguments a and b and implicit argument c. Example: d->g(a, b) has two explicit arguments a and b and implicit argument *d.

Note that an omitted implicit argument defaults to (this), which must make sense in the context. Example: If g is a member function of class MyClass, then within MyClass, the call g(a, b) defaults to (this).g(a,b) (or equivalently this->g(a,b)).


Good function prototypes

Pass by reference instead of by pointer. A pass by pointer may imply optional and the user may pass a null pointer:

Method(const Class *value); // value can be null Cannot pass a null pointer via reference
Method(const Class &value); // value cannot be null

Always include “const” unless the calling function needs to modify the state of passed reference

Do not pass simple data types (int, char, bool) by by const reference … it does not do anything good and may actually inhibit some optimizations


Casting!

int x = 5;
double y0 = (int) x;
double y1 = static_cast<int>(x);

Do not use C style casting it is difficult to find


Iterators Iterators are like generalized pointers into containers. Most pointer operations *, ->, ++, ==, !=, etc. work with iterators.

  • begin() returns an iterator pointing to the first element of the vector.
  • end() returns an iterator pointing past the last element of the vector.

class B : A { ... }; specifies private derivation of B from A.


Protected class members are inaccessible from outside the class (like private) but accessible within a derived class (like public).


ln16.pdf

  • The declaration context is the context in which the referent of x appears.
  • The reference context is the context in which the reference x appears.

Template functions and specialization

Template functions Definition:

template void swapargs(X& a, X& b) {

 X temp;
 temp = a;
 a = b;
 b = temp;

}

Use:

 int i,j;
 double x,y;
 char a, b;
 swapargs(i,j);
 swapargs(x,y);
 swapargs(a,b);

Specialization Definition:

 template <> void swapargs(int& a, int& b) {
   // different code
 }

This overrides the template body for int arguments.


Non-inline template functions must be compiled and linked for each instantiation

  • (a) Put all template function definitions in the .hpp file along with the class definition.
  • (b) Put template function definition in the .hpp file and explicitly instantiate all the possible types. e.g. template class FlexArray<int>; template class FlexArray<double>; ...

C casts. C uses the same syntax for different kinds of casts.

  • Value casts convert from one representation to another, partially preserving semantics. Often called conversions.
  • Pointer casts leave representation alone but change interpretation of pointer.

C++ casts

C++ has four kinds of casts.

  1. Static cast includes value casts of C. Tries to preserve semantics, but not always safe. Applied at compile time.
  2. Dynamic cast Applies only to pointers and references to objects. Preserves semantics. Applied at run time. [See demo 18c-Dynamic cast.]
  3. Reinterpret cast is like the C pointer cast. Ignores semantics. Applied at compile time.
  4. Const cast Allows const restriction to be overridden. Applied at compile time.

notation

int x; myBase* b; const int c;
static_cast<double>(x);
dynamic_cast<myDerived*>(b);
reinterpret_cast<int*>(p);
const_cast<int>(c);

explicit keyword inhibit implicit casts.

class B;
class A {
public:
    A(){};
    explicit A(B& b) { cout<< "constructed A from B\n"; }
};

C-style exception solution uses status returns

The C library functions generally report exceptions by returning status values or error codes.

C++ exception mechanism

Deriving your own exception classes from std::exception

#include <iostream>
#include <exception>
using namespace std;
class myexception: public exception {
  virtual const char* what() const throw()
    { return "My exception happened"; }
} myex;  // declares class and instantiates it
int main () {
  try {
    throw myex;
  }
  catch (exception& e) {
    cout << e.what() << endl;
  }
return 0; }

each kind of exception should throw it’s own type of object.


rethrow

throw e; will throw a new copy of e

throw; will not throw a new copy of e, but e itself


All exceptions should be caught and dealt with explicitly. That terminate() is called to abort the process is a bad thing when exceptions are not caught or thrown by the destructor.


multiple inheritance

class A: public B, protected C {…};

diamond pattern, A->B, A->C, {B,C}->D


Good Reference Books

C Programming Language, Effective C++, More Effective C++, Design Patterns


test

make test&& ./test

STL

Common wisdom on the internet says not to inherit from STL containers.

STL containers are not intended to be used as base classes (their destructors are deliberately non-virtual); deriving from a container is a common mistake.”


Two kinds of derivation

C++ supports two distinct kinds of derivation:

  • Simple derivation.
  • Polymorphic derivation.

    class A { … }; class B : public A { … };

We say B is derived from A, and B inherits members from A. Each B object has an A object embedded within it.The derivation is simple if no members of A are virtual; otherwise it is polymorphic.


What are the problems of polymorphic derivation? (ln13.pdf)

Every polymorphic base class (containing even one virtual function) adds a runtime type tag to each instance.

This costs in both time and space.

  • Time: Each call to a virtual function goes through a run-time dispatch table (the vtable).
  • Space: Each instance of a polymorphic object contains a type tag, which takes extra space.
  • Every polymorphic base class should have a virtual destructor.

General OO principles

  1. Encapsulation Data members should be private. Public accessing functions should be defined only when absolutely necessary. This minimizes the ways in which one class can depend on the representation of another.
  2. Narrow interface Keep the interface (set of public functions) as simple as possible; include only those functions that are of direct interest to client classes. Utility functions that are used only to implement the interface should be kept private. This minimizes the chance for information to leak out of the class or for a function to be used inappropriately.
  3. Delegation A class that is called upon to perform a task often delegates that task (or part of it) to one of its members who is an expert.

What is a design pattern?

A pattern has four essential elements.

  1. A pattern name.
  2. The problem, which describes when to apply the pattern.
  3. The solution, which describes the elements, relations, and responsibilities.
  4. The consequences, which are the results and tradeoffs.

Design Patterns

  • Adaptor matches interface between toolkit classes and applications.
  • Indirection decouples high-level applications from manipulations of low-level devices.
  • Proxy could interface to anything, is like indirection and controls access via a placeholder
  • Polymorphism enables multiple implementations from the abstraction
  • Controller handles system events
  • Bridge is generalized indirection and decouples interface from implementation. Used when both application and implementation are polymorphic.
  • Subject-observer: keep updated states of the subject with observers.
  • Singleton enforces only one instance of a class
  • Strategy defines a family of algorithms, encapsulates each one, and makes them interchangeable at run time.
    • The Bridge pattern is a structural pattern (HOW DO YOU BUILD A SOFTWARE COMPONENT?).
    • The Strategy pattern is a dynamic pattern (HOW DO YOU WANT RUN A BEHAVIOUR IN SOFTWARE?).
    • The syntax is similar but the goal are differents:
      • Bridge: you can split the hierarchy of interface and class join him with an abstract reference
      • Strategy: you have more ways for doing an operation; with strategy you can choice the algorithm at run-time and you can modify a single Strategy without a lot of side-effects at compile-time;
  • Factory method defines an interface for creating an object but lets the implementation decide which class to instantiate.

Factory

ImageReaderFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 public class ImageReaderFactory {
      public static ImageReader imageReaderFactoryMethod(InputStream is) {
          ImageReader product = null;

          int imageType = determineImageType(is);
          switch (imageType) {
              case ImageReaderFactory.GIF:
                  product = new GifReader(is);
                  break;
              case ImageReaderFactory.JPEG:
                  product = new JpegReader(is);
                  break;
              //...
          }
          return product;
      }
  }

Proxy

Real_Img_on_SystemA_and_Proxy_on_SystemB.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
interface Image {
    public void displayImage();
}

//on System A 
class RealImage implements Image {

    private String filename = null;
    /**
     * Constructor
     * @param FILENAME
     */
    public RealImage(final String FILENAME) {
        filename = FILENAME;
        loadImageFromDisk();
    }

    /**
     * Loads the image from the disk
     */
    private void loadImageFromDisk() {
        System.out.println("Loading   " + filename);
    }

    /**
     * Displays the image
     */
    public void displayImage() {
        System.out.println("Displaying " + filename);
    }

}

//on System B 
class ProxyImage implements Image {

    private RealImage image = null;
    private String filename = null;
    /**
     * Constructor
     * @param FILENAME
     */
    public ProxyImage(final String FILENAME) {
        filename = FILENAME;
    }

    /**
     * Displays the image
     */
    public void displayImage() {
        if (image == null) {
           image = new RealImage(filename);
        }
        image.displayImage();
    }

}

class ProxyExample {

   /**
    * Test method
    */
   public static void main(String[] args) {
        final Image IMAGE1 = new ProxyImage("HiRes_10MB_Photo1");
        final Image IMAGE2 = new ProxyImage("HiRes_10MB_Photo2");

        IMAGE1.displayImage(); // loading necessary
        IMAGE1.displayImage(); // loading unnecessary
        IMAGE2.displayImage(); // loading necessary
        IMAGE2.displayImage(); // loading unnecessary
        IMAGE1.displayImage(); // loading unnecessary
    }

}

Referencing composed and base objects. site:http://zoo.cs.yale.edu/classes/cs427/

C++ Basics

1. Properties of C++

  1. Widely used in the real world.
  2. Close to the machine and capable of producing efficient code.
  3. Gives a programmer fine control over the use of resources.
  4. OOP: Supports the object-oriented programming paradigm.
  5. Modularity: Supports modularity and component isolation.
  6. Correctness: Supports correctness through privacy, modularity, and use of exceptions.
  7. Reusable code: Supports reusabale code through derivation and templates.

2. C++ file types

  1. Header files (.hpp) contain various kinds of declarations needed by clients of a module. They must not contain definitions of non-inline functions.
  2. Implementation files (.cpp) contain definitions of non-inline functions and class methods and a few other kinds of things. Public declarations belong in the corresponding .hpp files.
  3. Object files (.o) contain the code generated by the compiler from one .cpp file.
  4. Static library files (.a) are archives (collections) of object files.
  5. Executable files commands ready to be run. File names have no extension. They must have the “execute” mode bit set. is compiled to produce a corresponding .o file.
  6. Linking: All of the .o files, together with needed code from library files, are combined to produce one executable file.

3. Stages of a program creation. Kinds of errors that can be discovered at each stage. Compilation and linking. What does each do? What files are needed? What files are produced?

Two stages:

  • Compilation: Each .cpp file For every symbol referenced in any of the .o files, a definition must be found in exactly one .o file or in a library.

Compiler errors at each stage:

  • Preprocessor errors: Missing #include files, mismatched #ifndf…#endif pairs, etc.
  • Compilation errors: Syntax, semantics, missing/erroneous declarations. Sometimes the file produced by the preprocessor and seen by the compiler is not what the programmer intended.
  • Linker errors are generally methods that were declared but never defined, often because of mismatched signatures. Duplicate definitions from different modules also detected here, e.g., multiple definitions of main().

4. Qualifiers: inline, const, static

4.1. Static data members - A static class variable must be declared and defined. - A static class member is declared by preceding the member declaration by the qualifier static. - A static class member is defined by having it appear in global context with an initializer but without static. - Must be defined only once.

Example In mypack.hpp file, inside class definition:

    class MyPack {
        static int instances; // count # instantiations

In mypack.cpp file:

    int MyPack::instances = 0;

4.2. Static function members

  • As with static variables, the are declared inside class by prefixing static.
  • They may be defined either inside the class (as inline functions) or outside the class.
  • If defined outside the class, the :: prefix must be used and the word static omitted.

4.3. const declares a variable (L-value) to be readonly.

If they are used at all, global variables should be const. It is not bad style to use a global const variable because you can do things with it that you cannot do with #define (initialize a constant object of a structured type).

Here are three different uses of the const qualifier in a pointer declaration:

        int const* p; //a mutable pointer to a constant int
        int* const p; //a constant pointer to a mutable int
        int const* const r; //a constant pointer to a constant int

A little trick: if you read the declaration statement from right to left, it will be much easier to figure out its meaning. For example:

        int const* p; //p is a pointer to a constant integer
        int* const p; //p is a constant pointer to an integer.

4.4. inline - Methods defined inside a class are inline (e.g., getN()). - Inline functions are recompiled for every call. - Inline avoids function call overhead but results in larger code size. - inline keyword makes following function definition inline. - Inline functions must be defined in the header (.hpp) file. Why? To expand the code of an inline function at the point of call, the compiler must have access to the function definition. The function prototype is insufficient.

5. C++ types: primitive (built-in) value types, class types, enum types, typedef, reference types, and pointer types.

Classes and objects

1. The roles of a class

  • A type from which objects (instances) can be formed. We say the instances belong to the class.
  • A collection of things that belong together; a struct with its associated functions.
  • A way to encapsulate behavior: a public interface with a private implementation.
  • A way to protect the integrity of data, providing the rest of the world with functions that provide a view of the data but no way to modify it.
  • A way to organize and automate allocation, initialization, and deallocation
  • A reusable module.
  • A way to break a complex problem down into manageable, semi-independent pieces, each with a defined interface.
  • An entity that can collaborate with other classes to perform a task

2. Class elements and class structure. class visibility.

2.1. Class elements

  • A class contains declarations for data members and function members (or methods).
  • int n; declares a data member of type int.
  • int getN(){ return n; } is a complete member function definition.
  • void sortData(); declares a member function that must be defined elsewhere.
  • By convention, member names begin with lower case letters and are written in camelCase.

2.2. Visibility

  • The visibility of declared names can be controlled.
  • public: declares that following names are visible outside of the class.
  • private: restricts name visibility to this class.
  • Public names define the interface to the class.
  • Private names are for internal use, like local names in functions.

3. Differences between a class definition and a class implementation. Importance of a class interface.

the public functions of a class are called the class interface.

4. Constructing/destructing objects.

5. Different kinds and roles of constructors: ctors, copy constructors, default constructors.

Whenever a class object is created, one of its constructors is called. If not specified otherwise, the default constructor is called. This is the one that takes no arguments. If you do not define the default constructor, then the null constructor (which does nothing) is used. This applies not only to the “outer” object but also to all of its embedded objects.

5.1. Ctors

(short for constructor/initializors) allow one to supply parameters to implicitly-called constructors.

Example:

    class B : A {  
        B( int n ) : A(n) {};  
        // Calls A constructor with argument n  
    };

5.2. Copy constructors

  • A copy constructor is automatically defined for each new class A and has prototype A(const A&). It initializes a newly created A object by making a shallow copy of its argument.
  • Copy constructors are used for call-by-value parameters.
  • Assignment uses operator=(), which by default copies the data members but does not call the copy constructor.
  • The results of the implicitly-defined assignment and copy constructors are the same, but they can be redefined to be different.

  • Initialization, assignment, copying of objects (and variables in general)

Initialization ctors Ctors also can be used to initialze primitive (non-class) variables.

Example:

    class  B {  
        int x;  
        const int y;  
        B( int n ) : x(n), y(n+1) {}; // Initializes x and y  
    };

Multiple ctors are separated by commas.

Ctors present must be in the same order as the construction takes place – base class ctor first, then data member ctors in the same order as their declarations in the class.

Initialization not same as assignment

Previous example using ctors is not the same as writing

    B( int n ) { y=n+1; x=n; };

The order of initialization differs.

const variables can be initialized but not assgined to.

Initialization uses the constructor (for class objects).

Initialization from another instance of the same type uses the copy constructor.

I/O

1. streams: cin, cout, cerr, and clog

  • cin is the standard input stream.
  • cout is the standard output stream.
  • cerr is the standard output stream for errors.
  • clog is the standard output stream for logging.

Standard output is called cout. Other predefined output streams are cerr and clog. They are usually initialized to standard output but can be redirected.

2. Handling files.

  • ifstream fin ( “myfile.in” ); opens stream fin for reading. This implicitly invokes the constructor ifstream( “myfile.in” ).
  • ifstream fin; creates an input stream not associated with a file. fin.open( “myfile.in” ); attaches it to a file. Can also specify open modes.
  • To test if fin failed to open correctly, write if (!fin) {…}.
  • To close, use fin.close();.

Can read a line into a buffer with fin.get(buf, buflen);. This function stops before the newline is read. To continue, one must move past the newline with a simple fin.get(ch); or fin.ignore();.

3. Manipulators.

Manipulators are objects that can be arguments of >> or << but do not necessarily produce data.

Example:

    cout << hex << x << y << dec << z << endl;

Prints x and y in hex and z in decimal. After printing z, a newline is printed and the output stream is flushed. Manipulators are used in place of C formats to control input and output formatting and conversions.

4. Kinds of I/O errors and ways to handle them.

5. Error flags, their meaning and how they are set.

I/O functions set status flags after each I/O operation. bad means there was a read or write error on the file I/O. fail means the data was not appropriate to the field, e.g., trying to read a non-numeric character into a numeric variable. eof means that the end of file has been reached. good means that the above three bits are all off.

The whole state can be read with one call to rdstate().

    // getting state of stream object
    #include <iostream>
    #include <fstream>
    using namespace std;

    int main () {
        ifstream is;
        is.open ("test.txt");
        if ( (is.rdstate() & ifstream::failbit ) != 0 ) // if failbit flag is on
            cerr << "Error opening 'test.txt'\n";
        return 0;
    }

Functions are also provided for testing useful combinations of status bits.

  • good() returns true if the good bit is set.
  • bad() returns true if the bad bit is set. This is not the same as !good().
  • fail() returns true if the bad bit or the fail bit is set.
  • eof() returns true if the eof bit is set.

As in C, correct end of file and error checking require paying close attention to detail of exactly when these state bits are turned on.

To continue after a bit has been set, must call clear() to clear it.

  1. Extending operators. What operators can be extend and how? Advantages of extending operators.

Operators can be extended to work with new types, for example, complex numbers. +-*/

The built-in arithmetic operators in C and C++ are generic; they are defined for all built-in numeric types. One of the purposes of an object-oriented language is to enable the programmer to define new classes and use them in the same ways that the built-in classes are used. Combining these two facts, we see a need to extend the built-in generic operators to work on new classes. An operator extension implements a built-in function for a new type in such a way that the intention and character of the original operator are preserved.

    inline  
    ostream& operator<<(ostream& out, const Square& sq) {  
        return sq.print(out);  
    }

Functions and methods

1. Passing data to a function. What are the different ways to pass data to a function? Advantages of each method.

  • Call by value: The argument values are copied into the parameter storage locations in the function’s stack frame. There is no way for the function to change values in main’s stack frame.
  • Call by pointer: The arguments must be addresses of integer variables in the caller’s stack frame. These addresses are stored in the parameter locations in the function’s stack frame. They permit the function to modify its caller’s memory locations.
  • Call by reference: The arguments must be integer variables in the caller’s stack frame. The addresses of these variables are stored in the parameter locations in the function’s stack frame, permitting the function to modify its caller’s memory locations.

TODO advantages

2. Receiving data from a function. How data can be passed back from a function? Can more than one value be returned?

  • Return by value.
  • Return by pointer.
  • Return by const T *
  • Return by reference
  • Return by const T &

      int ret0( int* ar ) { return ar[0]; } // Returns an integer R-value.
      int* ret1( int* ar ) { return &ar[1]; } // A pointer R-value.
      const int* ret2( int* ar ) { return &ar[2]; } // A read-only pointer R-value.
      int& ret3( int* ar ) { return ar[3]; } // An L-value (reference).
      const int& ret4( int* ar ) { return ar[4]; } // A read-only L-value reference.
    

Pointers and references

1. L-values and R-values.

Something that can appear on the left is called an L-value. Something that can appear on the right is called an R-value. Intuitively, an L-value is the address of a storage location – some place where a value can be stored. An R-value is a thing that can be placed in a storage location. R-values are sometimes called pure data values.

The declaration int x = 3; says several things:

  • All values that can be stored in x have type int.
  • The name x is bound (when the code is executed) to a storage location adequate to store an int.
  • The int value 3 is initially placed in x’s storage location.

The assignment statement x = 3; means the following:

  • Get an L-value from the left hand side (x).
  • Get an R-value from the right hand side (3).
  • Put the R value from step 2 into the storage location whose address was obtained from step 1.

Given int x = 3; int y = 4; Consider x = y; This is processed as before, except what does it mean to get an R-value from y?

Whenever an L-value is presented and an R-value is needed, automatic deferencing occurs.

This means to go the storage location specified by the presented L-value (y) and get its R-value (4).

Then the assignment takes place as before.

2. References vs. pointers

A pointer [reference value] is a primitive object with an associated L-value.

TODO

3. Relationship between a reference and a pointer.

TODO

Derivation

1. What is derivation?

One class can be derived from another.

Syntax:

    class A {  
    public:  
        int x;  
        ...  
    };  
    class B : public A {  
        int y;  
        ...  
    };

A is the base class; B is the derived class.

B inherits the members from A.

2. When to use and when not to use class derivation.

Use

  • To allow a family of related classes to share common parts.
  • To describe abstract interfaces like Java.
  • To allow generic methods with run-time dispatching.
  • To provide a clean interface between existing, non-modifiable code and added user code.

3. Structure of an object

Structure of an object A simple object is like a struct in C. It consists of a block of storage large enough to contain all of its data members. An object of a derived class contains an instance of the base class followed by the data members of the derived class.

Example:

    class B : A { …};
    B bObj;

Then “inside” of bObj is an A-instance!

4. Referencing composed and base objects.

4.1 Referencing a composed object

Contrast the previous example to

    class B { A aObj; …};
    B bObj;

Here B composes A.

The embedded A object can be referenced using data member name aObj, e.g., bObj.aObj.

4.2 Referencing a base object

    class A { public: int x; int y; …};
    class B : A { int y; …};
    B bObj;
  • The data members of A can be referenced directly by name.
  • x refers to data member x in class A.
  • y refers to data member y in class B.
  • A::y refers to data member y in class A.
  • this points to the whole object. Its type is B*. It can be coerced to type A*.

5. Construction/destruction rules.

5.1 Construction rules

The rule for an object of a simple class is:

  1. Call the constructor/initializer for each data member object in sequence.
  2. Call the constructor for the class.

The rule for an object of a derived class is:

  1. Call the constructor for the base class recursively.
  2. Call the constructor/initializer for each data member object of the derived class in sequence.
  3. Call the constructor for the derived class.

5.2 Destruction rules

When an object is deleted, the destructors are called in the opposite order.

The rule for an object of a derived class is:

  1. Call the destructor for the dervied class.
  2. Call the destructor for each data member object of the derived class in reverse sequence.
  3. Call the destructor for the base class.

Error

1. Five kinds of failures. When different errors can occur?

  • Memory leak—Dynamic storage that is no longer accessible but has not been deallocated.
  • Amnesia—Storage values that mysteriously disapper.
  • Bus error—Program crashes because of an attempt to access non-existant memory.
  • Segmentation fault—Program crashes because of an attempt to access memory not allocated to your process.
  • Waiting for eternity—Program is in a permanent wait state or an infinite loop.

2. Memory leaks – what they are, how they arise, how they can be detected and design patterns for avoiding them.

3. Memory management paradigms.

C++ Standard Library

1. What is the C++ Standard Library and how can it be used?

2. Two classes: stringstream and vector

stringstream – permits I/O to an in-memory string-like object.

vector – creates a growable array of objects of type T, where T can be any type.

Class stringstream

A stringstream object (in the default case) acts like an ostream object.

It can be used just like you would use cout.

The characters go into an internal buffer rather than to a file or device.

The buffer can be retrieved as a string using the str() member function.

stringstream example

Example: Creating a label from an integer.

    #include <sstream>  
    ...  
    int examScore=94;  
    stringstream ss;  
    string label;  
    ss << "Score=" << examScore;  
    label = ss.str();  
    cout << label << endl;
    This prints Score=94.

vector

vector myvec is something like the C array T myvec[].

The element type T can be any primitive, object, or pointer type.

One big difference is that a vector starts empty (in the default case) and it grows as elements are appended to the end.

Useful functions:

  • myvec.push_back( item ) appends item to the end.
  • myvec.size() returns the number of objects in myvec
  • myvec[k] returns the object in myvec with index k (assuming it exists.) Indices run from 0 to size()-1. Other operations on vectors
  • Other operations include creating an empty vector, inserting, deleting, and copying elements, scanning through the vector, and so forth.
  • Liberal use is made of operator definitions to make vectors behave as much like other C++ objects as possible.
  • Vectors implement value semantics, meaning type T objects are copied freely within the vectors.
  • If copying is a problem, store pointers instead. vector examples

You must

    #include <vector>.

Elements can be accessed using standard subscript notion.

Inserting at the beginning or middle of a vector takes time O(n).

Example:

    vector<int> tbl(10);  // creates length 10 vector of int  
    tbl[5] = 7;           // stores 7 in slot #5  
    cout << tbl[5];       // prints 7  
    tbl[10] = 4;          // illegal, but not checked!!!  
    cout << tbl.at(5);    // prints 7  
    tbl.at(10) = 4;       // illegal and throws an exception  
    tbl.push_back(4);     // creates tbl[10] and stores 4  
    cout << tbl.at(10);   // prints 4

Class dependencies

  1. Tightly coupled classes.

Class B depends on class A if B refers to elements declared within class A or to A itself.

A pair of classes A and B are tightly coupled if each depends on the other.

  1. Circular dependencies.

File list.hpp:

        #pragma once  
        #include "cell.hpp"  
        class List { ... };
        File cell.hpp:

        #pragma once  
        #include "list.hpp"  
        class Cell { ... };
        File main.cpp:

        #include "list.hpp"  
        #include "cell.hpp"  
        int main() { ... }

Resolving circular dependencies

  • Suppose the only reference to B in A is to declare a pointer. Then it works to put a “forward” declaration of B at the top of A.hpp, for example:
      class B;
      class A { B* bp; ... };
    
  • If a function defined in A references symbols of B, then the definition of the function must be moved outside the class and placed where it will be read after B has been read in, e.g., in the A.cpp file.
  • If the function needs to be inline, this is still possible, but it’s much trickier getting the inline function definition in the right place.

Visualization

  1. Unified Modeling Language (UML)

TODO

  1. Elementary design principles.

  2. Privacy

  3. Expert
  4. Creation
  5. Deletion
  6. Consistency
  7. Delegation
  8. Don’t talk to strangers
  9. Responsibility

Stanford, paper, slides, video

1. Problem

RAMCloud is a storage system helping developers manage large-scale DRAM storage, driven by the fact that large-scale Web applications need to cache large data in DRAM. (For example, Facebook cached 150TB DRAM in memcached out of 200TB of disk storage.)

In order to keep a high level of durability and availability without impacting system performance, RAMCloud has only one single copy of data in DRAM. The problem here is how to recover from crash within 1s~2s.

Columbia University, papers, slides, video

1. Problem

The popularity of smartphones results in the need that a user may purchase several smartphones for different uses. Virtual machine (VM) mechanisms may be the solution, which enables separate and isolated instances of a smartphone software stack to run on the same ARM hardware.

2. Challenges

Traditional VMs for desktops and servers can not be applied to smartphones for

  1. limited resources can not fully support running an another entire OS
  2. existing design cannot leverage new devices, such as GPS, camera, GPUs, …

3. Solution

Key observation: one app at a time

概述

方才在和朋友们一起去管理学院参加了王功权先生的讲座,期间做了一些笔记,稍作整理记录在此。王功权先生似乎并没有为这次演讲做过多的准备,也不愿意表现地太过正式,毕竟谈人生这种事情,还是需要明月夜短松冈这种微醺的情怀的。实际的情况可能是,他在从哥伦比亚大学过来的路上稍微用iPhone写了个提纲,讲述之前看了几眼,便开始侃侃而谈,当然,情到深处之时,还是让人颇有触动的,不愧为一位诗人。以下的记录纯属个人笔记,有我个人理解的偏差,并不能确保准确地反映王功权先生的观点,也不反映我自己的观点。

他讲述的这四点建议分别是:

  1. 规划未来不如调整现在
  2. 志存高远
  3. 选择意味着放弃
  4. 在美国就业,在中国创业

在其后的问答环节中,他回答同学们提出的两个问题:

  1. 简要介绍您现在在哥伦比亚大学东亚研究所研究的“公民社会”这一议题?
  2. 对经济管理类毕业生就业领域选择有那些建议?