[cpp]What are move semantics?


I find it easiest to understand move semantics with example code. Let’s start with a very simple string class which only holds a pointer to a heap-allocated block of memory:

#include <cstring>
#include <algorithm>

class string
    char* data;


    string(const char* p)
        size_t size = strlen(p) + 1;
        data = new char[size];
        memcpy(data, p, size);

Since we chose to manage the memory ourselves, we need to follow the rule of three. I am going to defer writing the assignment operator and only implement the destructor and the copy constructor for now:

        delete[] data;

    string(const string& that)
        size_t size = strlen(that.data) + 1;
        data = new char[size];
        memcpy(data, that.data, size);

The copy constructor defines what it means to copy string objects. The parameter const string& that binds to all expressions of type string which allows you to make copies in the following examples:

string a(x);                                    // Line 1
string b(x + y);                                // Line 2
string c(some_function_returning_a_string());   // Line 3

Now comes the key insight into move semantics. Note that only in the first line where we copy x is this deep copy really necessary, because we might want to inspect x later and would be very surprised if x had changed somehow. Did you notice how I just said x three times (four times if you include this sentence) and meant the exact same object every time? We call expressions such as x“lvalues”.

The arguments in lines 2 and 3 are not lvalues, but rvalues, because the underlying string objects have no names, so the client has no way to inspect them again at a later point in time. rvalues denote temporary objects which are destroyed at the next semicolon (to be more precise: at the end of the full-expression that lexically contains the rvalue). This is important because during the initialization of b and c, we could do whatever we wanted with the source string, and the client couldn’t tell a difference!

C++0x introduces a new mechanism called “rvalue reference” which, among other things, allows us to detect rvalue arguments via function overloading. All we have to do is write a constructor with an rvalue reference parameter. Inside that constructor we can do anything we want with the source, as long as we leave it in some valid state:

    string(string&& that)   // string&& is an rvalue reference to a string
        data = that.data;
        that.data = nullptr;

What have we done here? Instead of deeply copying the heap data, we have just copied the pointer and then set the original pointer to null. In effect, we have “stolen” the data that originally belonged to the source string. Again, the key insight is that under no circumstance could the client detect that the source had been modified. Since we don’t really do a copy here, we call this constructor a “move constructor”. Its job is to move resources from one object to another instead of copying them.

Congratulations, you now understand the basics of move semantics! Let’s continue by implementing the assignment operator. If you’re unfamiliar with the copy and swap idiom, learn it and come back, because it’s an awesome C++ idiom related to exception safety.

    string& operator=(string that)
        std::swap(data, that.data);
        return *this;

Huh, that’s it? “Where’s the rvalue reference?” you might ask. “We don’t need it here!” is my answer🙂

Note that we pass the parameter that by value, so that has to be initialized just like any other string object. Exactly how is that going to be initialized? In the olden days of C++98, the answer would have been “by the copy constructor”. In C++0x, the compiler chooses between the copy constructor and the move constructor based on whether the argument to the assignment operator is an lvalue or an rvalue.

So if you say a = b, the copy constructor will initialize that (because the expression b is an lvalue), and the assignment operator swaps the contents with a freshly created, deep copy. That is the very definition of the copy and swap idiom — make a copy, swap the contents with the copy, and then get rid of the copy by leaving the scope. Nothing new here.

But if you say a = x + y, the move constructor will initialize that (because the expression x + yis an rvalue), so there is no deep copy involved, only an efficient move. that is still an independent object from the argument, but its construction was trivial, since the heap data didn’t have to be copied, just moved. It wasn’t necessary to copy it because x + y is an rvalue, and again, it is okay to move from string objects denoted by rvalues.

To summarize, the copy constructor makes a deep copy, because the source must remain untouched. The move constructor, on the other hand, can just copy the pointer and then set the pointer in the source to null. It is okay to “nullify” the source object in this manner, because the client has no way of inspecting the object again.

I hope this example got the main point across. There is a lot more to rvalue references and move semantics which I intentionally left out to keep it simple. If you want more details please see my supplementary answer.



My first answer was an extremely simplified introduction to move semantics, and many details were left out on purpose to keep it simple. However, there is a lot more to move semantics, and I thought it was time for a second answer to fill the gaps. The first answer is already quite old, and it did not feel right to simply replace it with a completely different text. I think it still serves well as a first introduction. But if you want to dig deeper, read on🙂

Stephan T. Lavavej took the time provide valuable feedback. Thank you very much, Stephan!


Move semantics allows an object, under certain conditions, to take ownership of some other object’s external resources. This is important in two ways:

  1. Turning expensive copies into cheap moves. See my first answer for an example. Note that if an object does not manage at least one external resource (either directly, or indirectly through its member objects), move semantics will not offer any advantages over copy semantics. In that case, copying an object and moving an object means the exact same thing:
    class cannot_benefit_from_move_semantics
        int a;        // moving an int means copying an int
        float b;      // moving a float means copying a float
        double c;     // moving a double means copying a double
        char d[64];   // moving a char array means copying a char array
        // ...
  2. Implementing safe “move-only” types; that is, types for which copying does not make sense, but moving does. Examples include locks, file handles, and smart pointers with unique ownership semantics. Note: This answer discusses std::auto_ptr, a deprecated C++98 standard library template, which was replaced by std::unique_ptr in C++11. Intermediate C++ programmers are probably at least somewhat familiar with std::auto_ptr, and because of the “move semantics” it displays, it seems like a good starting point for discussing move semantics in C++11. YMMV.

What is a move?

The C++98 standard library offers a smart pointer with unique ownership semantics called std::auto_ptr<T>. In case you are unfamiliar with auto_ptr, its purpose is to guarantee that a dynamically allocated object is always released, even in the face of exceptions:

    std::auto_ptr<Shape> a(new Triangle);
    // ...
    // arbitrary code, could throw exceptions
    // ...
}   // <--- when a goes out of scope, the triangle is deleted automatically

The unusual thing about auto_ptr is its “copying” behavior:

auto_ptr<Shape> a(new Triangle);

      | triangle data |
  |   +-|-+ |
a | p | | | |
  |   +---+ |

auto_ptr<Shape> b(a);

      | triangle data |
  +---------+            +-----|---+
  |   +---+ |            |   +-|-+ |
a | p |   | |          b | p | | | |
  |   +---+ |            |   +---+ |
  +---------+            +---------+

Note how the initialization of b with a does not copy the triangle, but instead transfers the ownership of the triangle from a to b. We also say “a is moved into b” or “the triangle is moved from a to b“. This may sound confusing, because the triangle itself always stays at the same place in memory.

To move an object means to transfer ownership of some resource it manages to another object.

The copy constructor of auto_ptr probably looks something like this (somewhat simplified):

auto_ptr(auto_ptr& source)   // note the missing const
    p = source.p;
    source.p = 0;   // now the source no longer owns the object

Dangerous and harmless moves

The dangerous thing about auto_ptr is that what syntactically looks like a copy is actually a move. Trying to call a member function on a moved-from auto_ptr will invoke undefined behavior, so you have to be very careful not to use an auto_ptr after it has been moved from:

auto_ptr<Shape> a(new Triangle);   // create triangle
auto_ptr<Shape> b(a);              // move a into b
double area = a->area();           // undefined behavior

But auto_ptr is not always dangerous. Factory functions are a perfectly fine use case for auto_ptr:

auto_ptr<Shape> make_triangle()
    return auto_ptr<Shape>(new Triangle);

auto_ptr<Shape> c(make_triangle());      // move temporary into c
double area = make_triangle()->area();   // perfectly safe

Note how both examples follow the same syntactic pattern:

auto_ptr<Shape> variable(expression);
double area = expression->area();

And yet, one of them invokes undefined behavior, whereas the other one does not. So what is the difference between the expressions a and make_triangle()? Aren’t they both of the same type? Indeed they are, but they have different value categories.

Value categories

Obviously, there must be some profound difference between the expression a which denotes an auto_ptr variable, and the expression make_triangle() which denotes the call of a function that returns an auto_ptr by value, thus creating a fresh temporary auto_ptr object every time it is called. a is an example of an lvalue, whereas make_triangle() is an example of an rvalue.

Moving from lvalues such as a is dangerous, because we could later try to call a member function via a, invoking undefined behavior. On the other hand, moving from rvalues such as make_triangle() is perfectly safe, because after the copy constructor has done its job, we cannot use the temporary again. There is no expression that denotes said temporary; if we simply write make_triangle() again, we get a different temporary. In fact, the moved-from temporary is already gone on the next line:

auto_ptr<Shape> c(make_triangle());
                                  ^ the moved-from temporary dies right here

Note that the letters l and r have a historic origin in the left-hand side and right-hand side of an assignment. This is no longer true in C++, because there are lvalues which cannot appear on the left-hand side of an assignment (like arrays or user-defined types without an assignment operator), and there are rvalues which can (all rvalues of class types with an assignment operator).

An rvalue of class type is an expression whose evaluation creates a temporary object. Under normal circumstances, no other expression inside the same scope denotes the same temporary object.

Rvalue references

We now understand that moving from lvalues is potentially dangerous, but moving from rvalues is harmless. If C++ had language support to distinguish lvalue arguments from rvalue arguments, we could either completely forbid moving from lvalues, or at least make moving from lvalues explicit at call site, so that we no longer move by accident.

C++11’s answer to this problem is rvalue references. An rvalue reference is a new kind of reference that only binds to rvalues, and the syntax is X&&. The good old reference X& is now known as anlvalue reference. (Note that X&& is not a reference to a reference; there is no such thing in C++.)

If we throw const into the mix, we already have four different kinds of references. What kinds of expressions of type X can they bind to?

            lvalue   const lvalue   rvalue   const rvalue
X&          yes
const X&    yes      yes            yes      yes
X&&                                 yes
const X&&                           yes      yes

In practice, you can forget about const X&&. Being restricted to read from rvalues is not very useful.

An rvalue reference X&& is a new kind of reference that only binds to rvalues.

Implicit conversions

Rvalue references went through several versions. Since version 2.1, an rvalue reference X&& also binds to all value categories of a different type Y, provided there is an implicit conversion from Y to X. In that case, a temporary of type X is created, and the rvalue reference is bound to that temporary:

void some_function(std::string&& r);

some_function("hello world");

In the above example, "hello world" is an lvalue of type const char[12]. Since there is an implicit conversion from const char[12] through const char* to std::string, a temporary of type std::string is created, and r is bound to that temporary. This is one of the cases where the distinction between rvalues (expressions) and temporaries (objects) is a bit blurry.

Move constructors

A useful example of a function with an X&& parameter is the move constructor X::X(X&& source). Its purpose is to transfer ownership of the managed resource from the source into the current object.

In C++11, std::auto_ptr<T> has been replaced by std::unique_ptr<T> which takes advantage of rvalue references. I will develop and discuss a simplified version of unique_ptr. First, we encapsulate a raw pointer and overload the operators -> and *, so our class feels like a pointer:

template<typename T>
class unique_ptr
    T* ptr;


    T* operator->() const
        return ptr;

    T& operator*() const
        return *ptr;

The constructor takes ownership of the object, and the destructor deletes it:

    explicit unique_ptr(T* p = nullptr)
        ptr = p;

        delete ptr;

Now comes the interesting part, the move constructor:

    unique_ptr(unique_ptr&& source)   // note the rvalue reference
        ptr = source.ptr;
        source.ptr = nullptr;

This move constructor does exactly what the auto_ptr copy constructor did, but it can only be supplied with rvalues:

unique_ptr<Shape> a(new Triangle);
unique_ptr<Shape> b(a);                 // error
unique_ptr<Shape> c(make_triangle());   // okay

The second line fails to compile, because a is an lvalue, but the parameter unique_ptr&& sourcecan only be bound to rvalues. This is exactly what we wanted; dangerous moves should never be implicit. The third line compiles just fine, because make_triangle() is an rvalue. The move constructor will transfer ownership from the temporary to c. Again, this is exactly what we wanted.

The move constructor transfers ownership of a managed resource into the current object.

Move assignment operators

The last missing piece is the move assignment operator. Its job is to release the old resource and acquire the new resource from its argument:

    unique_ptr& operator=(unique_ptr&& source)   // note the rvalue reference
        if (this != &source)    // beware of self-assignment
            delete ptr;         // release the old resource

            ptr = source.ptr;   // acquire the new resource
            source.ptr = nullptr;
        return *this;

Note how this implementation of the move assignment operator duplicates logic of both the destructor and the move constructor. Are you familiar with the copy-and-swap idiom? It can also be applied to move semantics as the move-and-swap idiom:

    unique_ptr& operator=(unique_ptr source)   // note the missing reference
        std::swap(ptr, source.ptr);
        return *this;

Now that source is a variable of type unique_ptr, it will be initialized by the move constructor; that is, the argument will be moved into the parameter. The argument is still required to be an rvalue, because the move constructor itself has an rvalue reference parameter. When control flow reaches the closing brace of operator=, source goes out of scope, releasing the old resource automatically.

The move assignment operator transfers ownership of a managed resource into the current object, releasing the old resource. The move-and-swap idiom simplifies the implementation.

Moving from lvalues

Sometimes, we want to move from lvalues. That is, sometimes we want the compiler to treat an lvalue as if it were an rvalue, so it can invoke the move constructor, even though it could be potentially unsafe. For this purpose, C++11 offers a standard library function template called std::move inside the header <utility>. This name is a bit unfortunate, because std::move simply casts an lvalue to an rvalue; it does not move anything by itself. It merely enables moving. Maybe it should have been named std::cast_to_rvalue or std::enable_move, but we are stuck with the name by now.

Here is how you explicitly move from an lvalue:

unique_ptr<Shape> a(new Triangle);
unique_ptr<Shape> b(a);              // still an error
unique_ptr<Shape> c(std::move(a));   // okay

Note that after the third line, a no longer owns a triangle. That’s okay, because by explicitly writing std::move(a), we made our intentions clear: “Dear constructor, do whatever you want with a in order to initialize c; I don’t care about a anymore. Feel free to have your way with a.”

std::move(some_lvalue) casts an lvalue to an rvalue, thus enabling a subsequent move.


Note that even though std::move(a) is an rvalue, its evaluation does not create a temporary object. This conundrum forced the committee to introduce a third value category. Something that can be bound to an rvalue reference, even though it is not an rvalue in the traditional sense, is called anxvalue (eXpiring value). The traditional rvalues were renamed to prvalues (Pure rvalues).

Both prvalues and xvalues are rvalues. Xvalues and lvalues are both glvalues (Generalized lvalues). The relationships are easier to grasp with a diagram:

          /     \
         /       \
        /         \
    glvalues   rvalues
      /  \       /  \
     /    \     /    \
    /      \   /      \
lvalues   xvalues   prvalues

Note that only xvalues are really new; the rest is just due to renaming and grouping.

C++98 rvalues are known as prvalues in C++11. Mentally replace all occurrences of “rvalue” in the preceding paragraphs with “prvalue”.

Moving out of functions

So far, we have seen movement into local variables, and into function parameters. But moving is also possible in the opposite direction. If a function returns by value, some object at call site (probably a local variable or a temporary, but could be any kind of object) is initialized with the expression after thereturn statement as an argument to the move constructor:

unique_ptr<Shape> make_triangle()
    return unique_ptr<Shape>(new Triangle);
}          \-----------------------------/
                  | temporary is moved into c
unique_ptr<Shape> c(make_triangle());

Perhaps surprisingly, automatic objects (local variables that are not declared as static) can also beimplicitly moved out of functions:

unique_ptr<Shape> make_square()
    unique_ptr<Shape> result(new Square);
    return result;   // note the missing std::move

How come the move constructor accepts the lvalue result as an argument? The scope of resultis about to end, and it will be destroyed during stack unwinding. Nobody could possibly complain afterwards that result had changed somehow; when control flow is back at the caller, result does not exist anymore! For that reason, C++11 has a special rule that allows returning automatic objects from functions without having to write std::move. In fact, you should never use std::move to move automatic objects out of functions, as this inhibits the “named return value optimization” (NRVO).

Never use std::move to move automatic objects out of functions.

Note that in both factory functions, the return type is a value, not an rvalue reference. Rvalue references are still references, and as always, you should never return a reference to an automatic object; the caller would end up with a dangling reference if you tricked the compiler into accepting your code, like this:

unique_ptr<Shape>&& flawed_attempt()   // DO NOT DO THIS!
    unique_ptr<Shape> very_bad_idea(new Square);
    return std::move(very_bad_idea);   // WRONG!

Never return automatic objects by rvalue reference. Moving is exclusively performed by the move constructor, not by std::move, and not by merely binding an rvalue to an rvalue reference.

Moving into members

Sooner or later, you are going to write code like this:

class Foo
    unique_ptr<Shape> member;


    Foo(unique_ptr<Shape>&& parameter)
    : member(parameter)   // error

Basically, the compiler will complain that parameter is an lvalue. If you look at its type, you see an rvalue reference, but an rvalue reference simply means “a reference that is bound to an rvalue”; it does not mean that the reference itself is an rvalue! Indeed, parameter is just an ordinary variable with a name. You can use parameter as often as you like inside the body of the constructor, and it always denotes the same object. Implicitly moving from it would be dangerous, hence the language forbids it.

A named rvalue reference is an lvalue, just like any other variable.

The solution is to manually enable the move:

class Foo
    unique_ptr<Shape> member;


    Foo(unique_ptr<Shape>&& parameter)
    : member(std::move(parameter))   // note the std::move

You could argue that parameter is not used anymore after the initialization of member. Why is there no special rule to silently insert std::move just as with return values? Probably because it would be too much burden on the compiler implementors. For example, what if the constructor body was in another translation unit? By contrast, the return value rule simply has to check the symbol tables to determine whether or not the identifier after the return keyword denotes an automatic object.

You can also pass parameter by value. For move-only types like unique_ptr, it seems there is no established idiom yet. Personally, I prefer pass by value, as it causes less clutter in the interface.

Special member functions

C++98 implicitly declares three special member functions on demand, that is, when they are needed somewhere: the copy constructor, the copy assignment operator and the destructor.

X::X(const X&);              // copy constructor
X& X::operator=(const X&);   // copy assignment operator
X::~X();                     // destructor

Rvalue references went through several versions. Since version 3.0, C++11 declares two additional special member functions on demand: the move constructor and the move assignment operator. Note that neither VC10 nor VC11 conform to version 3.0 yet, so you will have to implement them yourself.

X::X(X&&);                   // move constructor
X& X::operator=(X&&);        // move assignment operator

These two new special member functions are only implicitly declared if none of the special member functions are declared manually. Also, if you declare your own move constructor or move assignment operator, neither the copy constructor nor the copy assignment operator will be declared implicitly.

What do these rules mean in practice?

If you write a class without unmanaged resources, there is no need to declare any of the five special member functions yourself, and you will get correct copy semantics and move semantics for free. Otherwise, you will have to implement the special member functions yourself. Of course, if your class does not benefit from move semantics, there is no need to implement the special move operations.

Note that the copy assignment operator and the move assignment operator can be fused into a single, unified assignment operator, taking its argument by value:

X& X::operator=(X source)    // unified assignment operator
    swap(source);            // see my first answer for an explanation
    return *this;

This way, the number of special member functions to implement drops from five to four. There is a tradeoff between exception-safety and efficiency here, but I am not an expert on this issue.

Forwarding references (previously known as Universal references)

Consider the following function template:

template<typename T>
void foo(T&&);

You might expect T&& to only bind to rvalues, because at first glance, it looks like an rvalue reference. As it turns out though, T&& also binds to lvalues:

foo(make_triangle());   // T is unique_ptr<Shape>, T&& is unique_ptr<Shape>&&
unique_ptr<Shape> a(new Triangle);
foo(a);                 // T is unique_ptr<Shape>&, T&& is unique_ptr<Shape>&

If the argument is an rvalue of type X, T is deduced to be X, hence T&& means X&&. This is what anyone would expect. But if the argument is an lvalue of type X, due to a special rule, T is deduced to be X&, hence T&& would mean something like X& &&. But since C++ still has no notion of references to references, the type X& && is collapsed into X&. This may sound confusing and useless at first, but reference collapsing is essential for perfect forwarding (which will not be discussed here).

T&& is not an rvalue reference, but a forwarding reference. It also binds to lvalues, in which case T and T&& are both lvalue references.

If you want to constrain a function template to rvalues, you can combine SFINAE with type traits:

#include <type_traits>

template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, void>::type

Implementation of move

Now that you understand reference collapsing, here is how std::move is implemented:

template<typename T>
typename std::remove_reference<T>::type&&
move(T&& t)
    return static_cast<typename std::remove_reference<T>::type&&>(t);

As you can see, move accepts any kind of parameter thanks to the forwarding reference T&&, and it returns an rvalue reference. The std::remove_reference<T>::type meta-function call is necessary because otherwise, for lvalues of type X, the return type would be X& &&, which would collapse into X&. Since t is always an lvalue (remember that a named rvalue reference is an lvalue), but we want to bind t to an rvalue reference, we have to explicitly cast t to the correct return type. The call of a function that returns an rvalue reference is itself an xvalue. Now you know where xvalues come from😉

The call of a function that returns an rvalue reference, such as std::move, is an xvalue.

Note that returning by rvalue reference is fine in this example, because t does not denote an automatic object, but instead an object that was passed in by the caller.

[cpp]What is the copy-and-swap idiom?




Why do we need the copy-and-swap idiom?

Any class that manages a resource (a wrapper, like a smart pointer) needs to implement The Big Three. While the goals and implementation of the copy-constructor and destructor are straightforward, the copy-assignment operator is arguably the most nuanced and difficult. How should it be done? What pitfalls need to be avoided?

The copy-and-swap idiom is the solution, and elegantly assists the assignment operator in achieving two things: avoiding code duplication, and providing a strong exception guarantee.

How does it work?

Conceptually, it works by using the copy-constructor’s functionality to create a local copy of the data, then takes the copied data with a swap function, swapping the old data with the new data. The temporary copy then destructs, taking the old data with it. We are left with a copy of the new data.

In order to use the copy-and-swap idiom, we need three things: a working copy-constructor, a working destructor (both are the basis of any wrapper, so should be complete anyway), and a swapfunction.

A swap function is a non-throwing function that swaps two objects of a class, member for member. We might be tempted to use std::swap instead of providing our own, but this would be impossible; std::swap uses the copy-constructor and copy-assignment operator within its implementation, and we’d ultimately be trying to define the assignment operator in terms of itself!

(Not only that, but unqualified calls to swap will use our custom swap operator, skipping over the unnecessary construction and destruction of our class that std::swap would entail.)

An in-depth explanation

The goal

Let’s consider a concrete case. We want to manage, in an otherwise useless class, a dynamic array. We start with a working constructor, copy-constructor, and destructor:

#include <algorithm> // std::copy
#include <cstddef> // std::size_t

class dumb_array
    // (default) constructor
    dumb_array(std::size_t size = 0)
        : mSize(size),
          mArray(mSize ? new int[mSize]() : 0)

    // copy-constructor
    dumb_array(const dumb_array& other)
        : mSize(other.mSize),
          mArray(mSize ? new int[mSize] : 0),
        // note that this is non-throwing, because of the data
        // types being used; more attention to detail with regards
        // to exceptions must be given in a more general case, however
        std::copy(other.mArray, other.mArray + mSize, mArray);

    // destructor
        delete [] mArray;

    std::size_t mSize;
    int* mArray;

This class almost manages the array successfully, but it needs operator= to work correctly.

A failed solution

Here’s how a naive implementation might look:

// the hard part
dumb_array& operator=(const dumb_array& other)
    if (this != &other) // (1)
        // get rid of the old data...
        delete [] mArray; // (2)
        mArray = 0; // (2) *(see footnote for rationale)

        // ...and put in the new
        mSize = other.mSize; // (3)
        mArray = mSize ? new int[mSize] : 0; // (3)
        std::copy(other.mArray, other.mArray + mSize, mArray); // (3)

    return *this;

And we say we’re finished; this now manages an array, without leaks. However, it suffers from three problems, marked sequentially in the code as (n).

  1. The first is the self-assignment test. This check serves two purposes: it’s an easy way to prevent us from running needless code on self-assignment, and it protects us from subtle bugs (such as deleting the array only to try and copy it). But in all other cases it merely serves to slow the program down, and act as noise in the code; self-assignment rarely occurs, so most of the time this check is a waste. It would be better if the operator could work properly without it.
  2. The second is that it only provides a basic exception guarantee. If new int[mSize] fails, *thiswill have been modified. (Namely, the size is wrong and the data is gone!) For a strong exception guarantee, it would need to be something akin to:
    dumb_array& operator=(const dumb_array& other)
        if (this != &other) // (1)
            // get the new data ready before we replace the old
            std::size_t newSize = other.mSize;
            int* newArray = newSize ? new int[newSize]() : 0; // (3)
            std::copy(other.mArray, other.mArray + newSize, newArray); // (3)
            // replace the old data (all are non-throwing)
            delete [] mArray;
            mSize = newSize;
            mArray = newArray;
        return *this;
  3. The code has expanded! Which leads us to the third problem: code duplication. Our assignment operator effectively duplicates all the code we’ve already written elsewhere, and that’s a terrible thing.

In our case, the core of it is only two lines (the allocation and the copy), but with more complex resources this code bloat can be quite a hassle. We should strive to never repeat ourselves.

(One might wonder: if this much code is needed to manage one resource correctly, what if my class manages more than one? While this may seem to be a valid concern, and indeed it requires non-trivialtry/catch clauses, this is a non-issue. That’s because a class should manage one resource only!)

A successful solution

As mentioned, the copy-and-swap idiom will fix all these issues. But right now, we have all the requirements except one: a swap function. While The Rule of Three successfully entails the existence of our copy-constructor, assignment operator, and destructor, it should really be called “The Big Three and A Half”: any time your class manages a resource it also makes sense to provide a swap function.

We need to add swap functionality to our class, and we do that as follows†:

class dumb_array
    // ...

    friend void swap(dumb_array& first, dumb_array& second) // nothrow
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;

        // by swapping the members of two classes,
        // the two classes are effectively swapped
        swap(first.mSize, second.mSize);
        swap(first.mArray, second.mArray);

    // ...

Now not only can we swap our dumb_array‘s, but swaps in general can be more efficient; it merely swaps pointers and sizes, rather than allocating and copying entire arrays. Aside from this bonus in functionality and efficiency, we are now ready to implement the copy-and-swap idiom.

Without further ado, our assignment operator is:

dumb_array& operator=(dumb_array other) // (1)
    swap(*this, other); // (2)

    return *this;

And that’s it! With one fell swoop, all three problems are elegantly tackled at once.

Why does it work?

We first notice an important choice: the parameter argument is taken by-value. While one could just as easily do the following (and indeed, many naive implementations of the idiom do):

dumb_array& operator=(const dumb_array& other)
    dumb_array temp(other);
    swap(*this, temp);

    return *this;

We lose an important optimization opportunity. Not only that, but this choice is critical in C++11, which is discussed later. (On a general note, a remarkably useful guideline is as follows: if you’re going to make a copy of something in a function, let the compiler do it in the parameter list.‡)

Either way, this method of obtaining our resource is the key to eliminating code duplication: we get to use the code from the copy-constructor to make the copy, and never need to repeat any bit of it. Now that the copy is made, we are ready to swap.

Observe that upon entering the function that all the new data is already allocated, copied, and ready to be used. This is what gives us a strong exception guarantee for free: we won’t even enter the function if construction of the copy fails, and it’s therefore not possible to alter the state of *this. (What we did manually before for a strong exception guarantee, the compiler is doing for us now; how kind.)

At this point we are home-free, because swap is non-throwing. We swap our current data with the copied data, safely altering our state, and the old data gets put into the temporary. The old data is then released when the function returns. (Where upon the parameter’s scope ends and its destructor is called.)

Because the idiom repeats no code, we cannot introduce bugs within the operator. Note that this means we are rid of the need for a self-assignment check, allowing a single uniform implementation of operator=. (Additionally, we no longer have a performance penalty on non-self-assignments.)

And that is the copy-and-swap idiom.

What about C++11?

The next version of C++, C++11, makes one very important change to how we manage resources: the Rule of Three is now The Rule of Four (and a half). Why? Because not only do we need to be able to copy-construct our resource, we need to move-construct it as well.

Luckily for us, this is easy:

class dumb_array
    // ...

    // move constructor
    dumb_array(dumb_array&& other)
        : dumb_array() // initialize via default constructor, C++11 only
        swap(*this, other);

    // ...

What’s going on here? Recall the goal of move-construction: to take the resources from another instance of the class, leaving it in a state guaranteed to be assignable and destructible.

So what we’ve done is simple: initialize via the default constructor (a C++11 feature), then swap with other; we know a default constructed instance of our class can safely be assigned and destructed, so we know other will be able to do the same, after swapping.

(Note that some compilers do not support constructor delegation; in this case, we have to manually default construct the class. This is an unfortunate but luckily trivial task.)

Why does that work?

That is the only change we need to make to our class, so why does it work? Remember the ever-important decision we made to make the parameter a value and not a reference:

dumb_array& operator=(dumb_array other); // (1)

Now, if other is being initialized with an rvalue, it will be move-constructed. Perfect. In the same way C++03 let us re-use our copy-constructor functionality by taking the argument by-value, C++11 willautomatically pick the move-constructor when appropriate as well. (And, of course, as mentioned in previously linked article, the copying/moving of the value may simply be elided altogether.)

And so concludes the copy-and-swap idiom.


*Why do we set mArray to null? Because if any further code in the operator throws, the destructor of dumb_array might be called; and if that happens without setting it to null, we attempt to delete memory that’s already been deleted! We avoid this by setting it to null, as deleting null is a no-operation.

†There are other claims that we should specialize std::swap for our type, provide an in-class swapalong-side a free-function swap, etc. But this is all unnecessary: any proper use of swap will be through an unqualified call, and our function will be found through ADL. One function will do.

‡The reason is simple: once you have the resource to yourself, you may swap and/or move it (C++11) anywhere it needs to be. And by making the copy in the parameter list, you maximize optimization.

[cpp]What is The Rule of Three?



If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.


C++ treats variables of user-defined types with value semantics. This means that objects are implicitly copied in various contexts, and we should understand what “copying an object” actually means.

Let us consider a simple example:

class person
    std::string name;
    int age;


    person(const std::string& name, int age) : name(name), age(age)

int main()
    person a("Bjarne Stroustrup", 60);
    person b(a);   // What happens here?
    b = a;         // And here?

(If you are puzzled by the name(name), age(age) part, this is called a member initializer list.)

Special member functions

What does it mean to copy a person object? The main function shows two distinct copying scenarios. The initialization person b(a); is performed by the copy constructor. Its job is to construct a fresh object based on the state of an existing object. The assignment b = a is performed by the copy assignment operator. Its job is generally a little more complicated, because the target object is already in some valid state that needs to be dealt with.

Since we declared neither the copy constructor nor the assignment operator (nor the destructor) ourselves, these are implicitly defined for us. Quote from the standard:

The […] copy constructor and copy assignment operator, […] and destructor are special member functions. [ Note: The implementation will implicitly declare these member functions for some class types when the program does not explicitly declare them. The implementation will implicitly define them if they are used. […] end note ] [n3126.pdf section 12 §1]

By default, copying an object means copying its members:

The implicitly-defined copy constructor for a non-union class X performs a memberwise copy of its subobjects. [n3126.pdf section 12.8 §16]

The implicitly-defined copy assignment operator for a non-union class X performs memberwise copy assignment of its subobjects. [n3126.pdf section 12.8 §30]

Implicit definitions

The implicitly-defined special member functions for person look like this:

// 1. copy constructor
person(const person& that) : name(that.name), age(that.age)

// 2. copy assignment operator
person& operator=(const person& that)
    name = that.name;
    age = that.age;
    return *this;

// 3. destructor

Memberwise copying is exactly what we want in this case: name and age are copied, so we get a self-contained, independent person object. The implicitly-defined destructor is always empty. This is also fine in this case since we did not acquire any resources in the constructor. The members’ destructors are implicitly called after the person destructor is finished:

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct […] members [n3126.pdf 12.4 §6]

Managing resources

So when should we declare those special member functions explicitly? When our class manages a resource, that is, when an object of the class is responsible for that resource. That usually means the resource is acquired in the constructor (or passed into the constructor) and released in the destructor.

Let us go back in time to pre-standard C++. There was no such thing as std::string, and programmers were in love with pointers. The person class might have looked like this:

class person
    char* name;
    int age;


    // the constructor acquires a resource:
    // in this case, dynamic memory obtained via new[]
    person(const char* the_name, int the_age)
        name = new char[strlen(the_name) + 1];
        strcpy(name, the_name);
        age = the_age;

    // the destructor must release this resource via delete[]
        delete[] name;

Even today, people still write classes in this style and get into trouble: “I pushed a person into a vector and now I get crazy memory errors!” Remember that by default, copying an object means copying its members, but copying the name member merely copies a pointer, not the character array it points to! This has several unpleasant effects:

  1. Changes via a can be observed via b.
  2. Once b is destroyed, a.name is a dangling pointer.
  3. If a is destroyed, deleting the dangling pointer yields undefined behavior.
  4. Since the assignment does not take into account what name pointed to before the assignment, sooner or later you will get memory leaks all over the place.

Explicit definitions

Since memberwise copying does not have the desired effect, we must define the copy constructor and the copy assignment operator explicitly to make deep copies of the character array:

// 1. copy constructor
person(const person& that)
    name = new char[strlen(that.name) + 1];
    strcpy(name, that.name);
    age = that.age;

// 2. copy assignment operator
person& operator=(const person& that)
    if (this != &that)
        delete[] name;
        // This is a dangerous point in the flow of execution!
        // We have temporarily invalidated the class invariants,
        // and the next statement might throw an exception,
        // leaving the object in an invalid state :(
        name = new char[strlen(that.name) + 1];
        strcpy(name, that.name);
        age = that.age;
    return *this;

Note the difference between initialization and assignment: we must tear down the old state before assigning to name to prevent memory leaks. Also, we have to protect against self-assignment of the form x = x. Without that check, delete[] name would delete the array containing the source string, because when you write x = x, both this->name and that.name contain the same pointer.

Exception safety

Unfortunately, this solution will fail if new char[...] throws an exception due to memory exhaustion. One possible solution is to introduce a local variable and reorder the statements:

// 2. copy assignment operator
person& operator=(const person& that)
    char* local_name = new char[strlen(that.name) + 1];
    // If the above statement throws,
    // the object is still in the same state as before.
    // None of the following statements will throw an exception :)
    strcpy(local_name, that.name);
    delete[] name;
    name = local_name;
    age = that.age;
    return *this;

This also takes care of self-assignment without an explicit check. An even more robust solution to this problem is the copy-and-swap idiom, but I will not go into the details of exception safety here. I only mentioned exceptions to make the following point: Writing classes that manage resources is hard.

Noncopyable resources

Some resources cannot or should not be copied, such as file handles or mutexes. In that case, simply declare the copy constructor and copy assignment operator as private without giving a definition:


    person(const person& that);
    person& operator=(const person& that);

Alternatively, you can inherit from boost::noncopyable or declare them as deleted (C++0x):

person(const person& that) = delete;
person& operator=(const person& that) = delete;

The rule of three

Sometimes you need to implement a class that manages a resource. (Never manage multiple resources in a single class, this will only lead to pain.) In that case, remember the rule of three:

If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.

(Unfortunately, this “rule” is not enforced by the C++ standard or any compiler I am aware of.)


Most of the time, you do not need to manage a resource yourself, because an existing class such as std::string already does it for you. Just compare the simple code using a std::string member to the convoluted and error-prone alternative using a char* and you should be convinced. As long as you stay away from raw pointer members, the rule of three is unlikely to concern your own code.




DTMB,全称Digital TelevisionTerrestrial Multimedia Broadcasting(中文:地面数字电视广播)

在数字电视地面、有线、卫星传输方式中,数字电视地面传输系统环境最为复杂,也因其技术要求最高、受众广而备受关注。地面系统的标准化工作也十分重要。目 前已有美国高级电视系统委员会(ATSC)、欧洲数字视频地面广播(DVB-T)和日本地面综合业务数字广播(ISDB-T)三个国际电联批准的地面数字 电视广播传输国际标准。1999年我国设立数字电视研发及产业化并成立国家数字电视领导小组,明确宣示自主制定技术标准。针对我国数字电视应用的具体标 准,2006年推出了我国数字电视地面标准DTMB。

在国家广播电影电视总局支持下,我国于2006年8月18 日正式颁布了《数字电视地面广播传输系统帧结构、信道编码和调制》(GB20600-2006)地面数字电视广播传输标准,实现了固定电视和公共交通移动 电视的数字电视信号传送。DTMB于2007年8月1号成为中国广播业地面电视信号的强制标准。

DTMB 系统能有效支持包括高清晰度电视(HDTV)、标清电视(SDTV)和多媒体数据广播等多种业务,同时完全满足大范围固定覆盖和移动接收需要。2007年 6月4日,香港电信管理局(OFTA)正式宣布从7月1日起采用DTMB进行试播。2009年,澳门也宣布了将采用与香港相同模式进行播出的计划。 2008年1月1日起国内多个城市开始了DTMB试播。奥运期间,7个奥运比赛城市播出了HDTV节目,为DTMB的大范围推广积累了经验。


% Q# J4 l( B+ m5 a  h0 v4 R

上面的资料我们知道DTMB是地面数字电视信号标准,那什么是地面数字 电视信号?我们知道数字电视技术主要分为地面数字电视、卫星数字电视和有线数字电视三种,其中地面数字电视信号是电视节目频道通过信号发射塔以地面波的方 法传输,信号覆盖范围内的用户可架设接收天线接收到地面数字电视信号。


1. 首先要确定当地的电视信号发射塔发出(不是每个地方的电视信号发射塔发出的信号都是DTMB数字电视信号,还有很多地方还是模拟电视信号),并在信号覆盖 范围之内(覆盖范围要视乎信号发射塔的发射功率和地形环境),目前主要大城市地面电视信号已经转换为DTMB数字电视信号。


我的小米电视是2013年10月15号首批抢到的,我们当地能接收到香港和深圳发出 的DTMB高清数字电视信号,为了感受小米电视的高清大屏,还专门另外购买了支持DTMB的机顶,2014年后抢购到小米电视并当地有DTMB数字电视信 号覆盖的就可以省略这个机顶盒。那DTMB数字电视信号有什么特点和功能呢?因为我的小米电视没有DTMB功能,我只有用我的DTMB机顶盒给大家简单介 绍一下





原版高质量16:9 + 1080p高清画面






[fwd]Android 音频系统


0. 专用术语

1. 物理结构

2. 系统架构


本文基于Freescale IMX平台Codec ALC5625为例。

0. 专用术语

 ASLA – Advanced Sound Linux Architecture

 OSS – 以前的Linux音频体系结构,被ASLA取代并兼容

 Codec – Coder/Decoder

 I2S/PCM/AC97 – Codec与CPU间音频的通信协议/接口/总线

 DAI – Digital Audio Interface 其实就是I2S/PCM/AC97

 DAC – Digit to Analog Conversion

 ADC – Analog to Digit Conversion

 DSP – Digital Signal Processor

 Mixer – 混音器,将来自不同通道的几种音频模拟信号混合成一种模拟信号

 Mute – 消音,屏蔽信号通道

 PCM – Pulse Code Modulation 一种从音频模拟信号转换成数字信号的技术,区别于PCM音频通信协议

 采样频率 – ADC的频率,每秒采样的次数,典型值如44.1KHZ

 量化精度 – 比如24bit,就是将音频模拟信号按照2的24次方进行等分

 SSI – Serial Sound Interface

 DAPM – Dynamic Audio Power Management


1. 物理结构



 I2C总线 – 实现对Codec寄存器数据的读写。

 DAI – 实现音频数据在CPU和Codec间的通信。


1) 播放音乐


2) 录音


3) 电话

— 打电话 —                                                           — 接听—


4) 通过蓝牙打电话

— 打电话 —                                                           — 接听—   




 2. 系统架构

  Android的音频系统拥有一个比较标准和健全的架构,从上层应用,java framework服务AudioMananger,本地服务AudioFlinger,抽象层AlsaHAL,本地库,再调用external的 Alsa-lib外部支持库,最后到底层驱动的codec,可谓”五脏俱全”。

 以系统启动AuidoFlinger为例,简要窥探Alsa Sound的组织架构。

Java服务AudioManager作为服务端,本地服务AudioFlinger作为客户端,两者通过Binder机制交互。 AudioFlinger对硬件功能的具体实现(比如setMode设置电话/蓝牙/录音等模式)交给硬件抽象层AlsaHAL完成。抽象层可以调用本地 标准接口,比如mASLADevice->route,或者直接调用Alsa-lib库去操作底层驱动。


 Linux的音频驱动结构相对复杂,源码位于内核目录下的/sound/soc/,其中/codec文件夹下存放与平台无关的编解码器驱动,/imx文件夹下存放于freescale imx平台相关的音频驱动,主要可分为SSI驱动和DAI驱动。


1) struct snd_soc_codec – 由与平台无关的codec驱动实现。

2) struct snd_soc_platform – 由与imx平台相关的DAI驱动实现,主要实现了音频数据的DMA传输功能。

3) struct snd_soc_dai_link – 将平台相关的DAI与平台无关的codec联系起来。




三维直角坐标系是一种利用直角坐标(x,y,z)来表示一个点 P 在三维空间的位置的三维正交坐标系


在三维空间的任何一点 P ,可以用直角坐标(x,y,z)来表达其位置。如左下图显示了三维直角坐标的几何意义:点P在x-轴、y-轴、z-轴上的投影距离分别为x、y、z。如右下图所示,两个点 P 与 Q 的直角坐标分别为(3,0,5)与(-5,-5,7) 。


球坐标系是一种利用球坐标(r,θ,φ)来表示一个点 P 在三维空间的位置的三维正交坐标系


假设 P 点在三维空间的位置的三个坐标是 (r,\ \theta,\ \phi)。那么, 0 ≤ r 是从原点到 P 点的距离, 0 ≤ θ ≤ π 是从原点到 P 点的连线与正 z-轴的夹角, 0 ≤ φ < 2π 是从原点到 P 点的连线在 xy-平面的投影线,与正 x-轴的夹角。当 r=0 时,\theta 与 \phi 都一起失去意义。当 \theta = 0 或 \theta = \pi 时,\phi 失去意义。



{r}=\sqrt{x^2 + y^2 + z^2} 、

{\theta}=\arctan \left( \frac{\sqrt{x^2 + y^2}}{z} \right)=\arccos \left( {\frac{z}{\sqrt{x^2 + y^2 + z^2}}} \right) 、

{\phi}=\arctan \left( {\frac{y}{x}} \right) 。


x=r \sin\theta \cos\phi 、

y=r \sin\theta \sin\phi 、

z=r \cos\theta 。



一直对齐次坐标这个概念的理解不够彻底,只见大部分的书中说道“齐次坐标在仿射变换中非常的方便”,然后就没有了后文,今天在一个叫做“三百年 重生”的博客上看到一篇关于透视投影变换的探讨的文章,其中有对齐次坐标有非常精辟的说明,特别是针对这样一句话进行了有力的证明:“齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。”—— F.S. Hill, JR。


对于一个向量v以及基oabc,可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c (1)

而对于一个点p,则可以找到一组坐标(p1,p2,p3),使得 p – o = p1 a + p2 b + p3 c (2),

从上面对向量和点的表达,我们可以看出为了在坐标系中表示一个点(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p – o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)

(1)(3)是坐标系下表达一个向量和点的不同表达方式。这里可以看出,虽然都是用代数分量的形式表达向量和点,但表达一个点比一个向量需要额外的信息。如果我写出一个代数分量表达(1, 4, 7),谁知道它是个向量还是个点!

我们现在把(1)(3)写成矩阵的形式:v = (v1 v2 v3 0) X (a b c o)

p = (p1 p2 p3 1) X (a b c o),这里(a,b,c,o)是坐标基矩阵,右边的列向量分别是向量v和点p在基下的坐标。这样,向量和点在同一个基下就有了不同的表达:3D向量的第4个代数分量是0,而3D点的第4个代数分量是1。像这种这种用4个代数分量表示3D几何概念的方式是一种齐次坐标表示。

这样,上面的(1, 4, 7)如果写成(1,4,7,0),它就是个向量;如果是(1,4,7,1),它就是个点。下面是如何在普通坐标(Ordinary Coordinate)和齐次坐标(Homogeneous Coordinate)之间进行转换:









此外,对于一个普通坐标的点P=(Px, Py, Pz),有对应的一族齐次坐标(wPx, wPy, wPz, w),其中w不等于零。比如,P(1, 4, 7)的齐次坐标有(1, 4, 7, 1)、(2, 8, 14, 2)、(-0.1, -0.4, -0.7, -0.1)等等。因此,如果把一个点从普通坐标变成齐次坐标,给x,y,z乘上同一个非零数w,然后增加第4个分量w;如果把一个齐次坐标转换成普通坐标,把前三个坐标同时除以第4个坐标,然后去掉第4个分量。

由于齐次坐标使用了4个分量来表达3D概念,使得平移变换可以使用矩阵进行,从而如F.S. Hill, JR所说,仿射(线性)变换的进行更加方便。由于图形硬件已经普遍地支持齐次坐标与矩阵乘法,因此更加促进了齐次坐标使用,使得它似乎成为图形学中的一个标准。


[fwd]install vs. cp; and mmap


1.系统使用mmap的方式映射binary executables 和 shared libraries来运行



If we hand write a Makefile, we should always stick to install instead of using cp for the installation commands. Not only is it more convenient, but it does things right (cp does things wrong).

For example, if we attempt to update /bin/bash, which is currently running, with “cp ... /bin/bash”, we get a “text busy” error. If we attempt to update /lib/libc.so.6 with “cp ... /lib/libc.so.6”, then we either get “text busy” (in ancient versions of Linux) or breaks each and every running program within a fraction of a second (in recent versions of Linux). install does the thing right in both situations.

The reason why cp fails is that it simply attempts to open the destination file in write-only mode and write the new contents. This causes problem because Linux (and all contemporary Unices as well as Microsoft Windows) uses memory mapping (mmap) to load executables and dynamic libraries.

The contents of an executable or dynamic library are mmap’d into the linear address space of relevant processes. Therefore, any change in the underlying file affects the mmap’d memory regions and can potentially break programs. (MAP_PRIVATE guarantees changes by processes to those memory regions are handled by COW without affecting the underlying file. On the contrary, POSIX leaves to implementations whether COW should be used if the underlying file is modified. In fact, for purpose of efficiency, in Linux, such modifications are visible to processes even though MAP_PRIVATE may have be used.)

There is an option MAP_DENWRITE which disallows any modification to the underlying file, designed to avoid situations described above. Executables and dynamic libraries are all mmap’d with this option. Unfortunately, it turned out MAP_DENYWRITE became a source of DoS attacks, forcing Linux to ignore this option in recent versions.

Executables are mmap’d by the kernel (in the execve syscall). For kernel codes, MAP_DENYWRITE still works, and therefore we get “text busy” errors if we attempt to modify the executable.

On the other hand, dynamic libraries are mmap’d by userspace codes (for example, by loaders like /lib/ld-linux.so). These codes still pass MAP_DENYWRITE to the kernel, but newer kernels silently ignores this option. The bad consequence is that you can break the whole system if you think you’re only upgrading the C runtime library.

Then, how does install solve this problem? Very simple – unlinking the file before writing the new one. Then the old file (no longer present in directory entries but still in disk until the last program referring to it exits) and the new file have different inodes. Programs started before the upgrading (continuing using the old file) and those after the upgrading (using the new version) will both be happy.

[fwd]王齐 。《后科技年代--操作系统的思考》



自有文字记载开始,历史向前推进了五千余年。在这段并不算漫长的时间里,生活在今天的人类是幸运的。我们的祖先没有像今天这样容易地获取食物,在遥 远的彼岸,美国用3%的农业人口养活了97%的非农业人口;人类历史上的所有帝王将相没有像今天的普通人这样容易地获得信息,互联网的出现使得汗牛塞屋的 图书馆模式成为过去;国家的边界没有像今天这样模糊,公司的崛起在不断跨越着时间与空间;移动互联网的出现,使得虚拟世界与现实世界的边界,没有像今天这 样模糊。我们处在一场前所未有的盛世之中。

这场盛世源于硅的出现。每在回味硅工业的发展历程,我总在质疑这段历史的真实性。硅工业的诞生是一段传奇,这一传奇超越了人类历经五千年农业与工业 积累而后的想象。很多人在质疑究竟是人还是神发现了硅。这些质疑无法改变硅工业对整个世界造成的巨大影响,我们现今世界的一切几乎都与硅有关。硅工业的不 断演化加快了世间万物的新旧更迭。在硅工业持续发展的60余年时间里,世间万物的产生,发展,消亡,过于匆忙,一个时代尚未结束,一个新的时代已在我们不 及回味中跃上舞台。我们处于一场前所未有的乱世之中。

硅工业在持续改变其他行业的过程中,改变了自身。硅工业的发展分为三个阶段,硅晶体管的诞生到集成电路的出现;摩尔定律持续正确那段只属于硅工业 的,最美好的一段时光;如今的后摩尔时代。在第二段时间里,硅工业迅猛发展,Intel在此时发展壮大。准确地讲,只有在这段时间,Intel才是 Intel,天下之士可以仅凭使命加入这家公司,投入这场令人热血沸腾的,只属于硅的时代。

硅工业至今依然在进步,却无法回避一个事实。如同人类历史上其他伟大发明,硅工业正在逐步退去光环。硅工业不是不再重要,而是渗透到了人类所能触及 的每一个领域,正式成为传统工业的重要组成部分。无论Intel在近期或是将来推出再多的Tick,也无法改变一个事实,硅工业正在逐步失去前进的动力。

硅的举步维艰并不会使其从人们的视野中淡出,而是我们越来越离不开硅。基于硅的各种设备将继续出现在世界的每一个角度,如食物衣服般同等重要。但是 我们有谁能知道身上衣,口中食出自哪个农民之手。如今的硅工业已经重要得让越来越多的人忘记了他的重要性。硅工业的这一现状将对其几个最重要的分支带来直 接的影响,处理器和附着在处理器之上的传统操作系统,和一切与此相关的,曾经辉煌的生态环境。

我已有很长一段时间不再如嗜血般关注处理器微架构,这个行业依然波澜不惊,偶尔冷静思考这门学科的未来,却再也难以找到在这个领域投入更多时间的理 由。在工程界,即便是在理论界,已没有什么可以令热血为之沸腾的发现。偶尔看些论文,无论是曾经Most Influential的经典,或是近期出现的一些说法,从中看到的不过是一些近亲繁殖的影子。

处理器微架构, x86还是ARM,采用什么样的集成策略,究竟使用什么工艺都已不再重要。从最近的这段时间看,在传统的PC领域,x86没有取得明显的进步,在手持终端 领域,ARM占尽先机。如果这种趋势一直持续,在可以预期的3到5年之内,如果Intel没有做出重大且激进的变革,将逐步远离二十一世纪最伟大的公司行 列。

ARM在手持移动领域的领先并不意味着这个阵营的伟大,而是x86阵营打败了自己。念及这段即将别离的往事,心中所思所想的是6500万年前白垩纪 恐龙的灭绝。在处理器微架构领域,这个时代已经没有留出更多的空间去继续容纳着庞然大物。ARM可以化整为零,活得稍好些。从更长远的角度上看,x86与 ARM间没有赢家。x86与ARM之争对参与的双方依然重要,却偏离了这个时代的主战场。这个时代不再属于硅与处理器微架构,依托在处理器微架构之上的传 统操作系统也已是昨日黄花。

在1975年,比尔盖兹也许未曾设想他一手创建的公司,可以在很短的时间内,垄断着桌面操作系统的一切。这种垄断,经过无限放大后,使微软可以涉及 与桌面软件相关的任何领域。当时的微软没有任何实质性对手。微软的前行,伴随着众多公司的倒塌。这家公司在最强大的时候,甚至可以采用“模仿你,不行就和 你比流血,再不行就挖光你的人”这样令人毛骨悚然的手段。通过与Intel事实上的联姻,组成的PC帝国,在很长一段时间里,所向无敌。因为这种无敌所产 生的自信,使得微软并没有真正重视周边环境的变化。

微软的产品,无论是哪种形态,近些年都在做一件相同的事情,不断引入一些可能并不需要的Feature,然后将这个由众多Feature组成的庞然大物呈 现在不知所措的用户面前。微软的这种做法,迷惑的不仅是用户,可怕的是迷惑了自己的双眼。诸多Feature的齐头并进,甚至使开发者忘记了设计初衷,忘 记了真正应该做的事情。我可能依然错误估计了这些设计者,也许他们的设计初衷就是尽可能多地罗列Feature,这些Feature有很大的一部分还是从 他处借来的。

软件帝国的产品名目虽多,却被罗列Feature这种设计模式笼罩,无论是Office,Windows Phone,Windows系列,还是近期发布Surface。Windows 8断不是微软宣称的革命化的操作系统,只是先将Windows Phone 8和Windows 7的界面合二为一,再将从PC领域继承来的Feature与手持终端领域中借来的Feature重新排列组合,最后加上支持ARM微架构这个 Feature。曾被基于厚望的Surface无论是RT还是Pro版本,带给软件帝国的除了失望还是失望。这个产品估计只剩下一个能力,就是可能可以打 败PC帝国的超级本或者变形本。

Windows和Surface的设计模式延续着软件帝国产品设计的定式,从Features上看,这些产品无所不有,也一无所有。这些 Feature的罗列没有改变微软的处境,却使得微软的所有产品进一步单一化,使得Office,Exchange,Windows间的耦合更加紧密,成 为事实上的单一产品。在我们所处的移动互联网时代,软件帝国正在逼着芸芸众生为他们这个单一产品做一道单选题,使用还是放弃。软件帝国的危机已迫在眉睫。

移动互联的兴起,使得传统的,大而全的微软思路轻易成为过去。软件帝国引以为豪的桌面操作系统,历经多年的演化,已经从之前的管理硬件资源,以处理 器系统为中心,逐步迁移到管理软件应用,以SDK为中心。传统操作系统的进程调度,内存管理,中断异常处理,输入输出,文件系统等其他组成模块已成往事。 这些组成模块的重要性在十几年前已经被清晰地认知,已是被Linux 2.6完成了七七八八的事情。

桌面操作系统只剩下Windows,Mac OS X和基于Linux的若干发布包。从个人的喜好上,我偏爱Mac OS X,只是理智在不停地告诉自己,这些操作系统将随PC时代的落幕,谈去色彩。我认同乔布斯说过的,PC更像是卡车这句话。如同卡车依然在世间扮演重要角色 一般,PC不会从地球中消失,而是回归到原本应该处于的场所。曾几何时,PC可以进入千家万户的原因和30多年前我们除了可以用卡车载货,还能兼职运人是 相同的道理。我们至今依然可以发现,在某些地区卡车还在做这些兼职工作。

更多的人不会让PC做这些兼职,PC将很快地转变为BC (Business Computer),失去Personal这个定语已近在咫尺。失去了Personal的PC帝国已经没有什么可以继续失去了。PC帝国并非对此一无所 知,却始终难以作出有效的改变。微软从来没有放弃在移动互联领域的努力;Intel在2006年暂时退出手机芯片后,在第二年就开始了Moblin的研发 工作,直到今天依然坚守着Tizen。这些项目从准备到最后的黯然离场,是如此正常,如此理所应当。

PC帝国之悲!不在于错过了移动互联网,不在于错过了手持终端,可能也不在于我们所察觉到的诸多问题。PC帝国从来没有错过这些机会。不是手持移动 互联时代打败了PC帝国,这个帝国从头到尾都是被自己打败的。当一个公司的前途掌握在给华尔街看的财务报表时,微软不再是微软,Intel不再是 Intel。世上多数公司,危机的种子早在成立的当天种下,在Funder们陆续离开这家公司时出现转折。比尔盖兹离开微软,格罗夫离开Intel时,微 软不是微软,Intel不是Intel了。PC帝国已经长得太大,大到了没有几个员工再把这里当做家。

PC帝国永远明白自己的问题,却不知如何解决。可以导致昔日洛阳纸贵的产品,弃之如敝屣。丢掉了,捡不回来了,再也没有必要捡回来了,开始全力以 赴。凝视PC帝国的努力,心如万马奔腾。并非这个帝国人才匮乏,事实恰好相反,很多人早已远望冰山,却无法改变这支巨舰,开足马力,奋而向前的方向。一个 曾经强大的国家,一个曾经强大的公司在即将退出历史舞台时,往往具备一个相同的特性,分明人才遍野却视若不见,君臣举手无措,视面而泣。君非亡国之君,臣 非亡国之臣,做实了亡国君臣。


在前PC和PC时代,电子信息领域所创造的几乎每一个产品,是由工程师定义定义,发明,创造的。我们一直再倾听客户的反馈,特别是在自己迷失之时, 只是经常忘记这些反馈恰是我们对客户反复不断洗脑而后得的衍生物罢了。在PC领域的人群习惯了这种从定义到反馈近亲繁殖的设计思路,习惯了这种至死方休的 套路。

乔布斯的苹果从这种思路中解脱,更加清楚未来进入千家万户的产品,不应该由工程师评判,用一只手就击溃了PC帝国的根基,终结了一个时代,引领了另 一个时代。如果仅从纯技术的角度上分析,我们很难得出在PC时代与移动互联时代中出现的产品,孰优孰劣的直接结论。无论iOS或者Android,所做最 多的努力是不断将昔日应用进一步OS化。这些努力使得产品更加易用。从未接触过计算机的老奶奶们可以轻松自如地使用基于Android或是iOS的产品, 尽管这些人到死也学不会如何使用桌面操作系统。

当移动互联领域的这些产品呈现在我们面前时,依然有许多个体,群体和公司想到的还是继续排列这些新Feature,想着需要多少个人月才能复制抄袭 已经发生的一切,继续下一个轮回的近亲迭代。在智能手机操作系统领域,除了统治地位的Android与iOS,有过辉煌的BlackBerry,始终坚持 着的Windows Phone,后继者源源不绝。Firefox,Ubuntu陆续发布了自己的手机操作系统。Intel从Moblin,Meego开始,直到Tizen。


单纯从Feature上看,这些后继者的某些Feature甚至超过了Android或者iOS。从全局上看,这些后继者更多的努力依然是在做近亲 繁殖与抄袭。从使用者的角度上看,基于Android与iOS的智能手机,的确产生了一些审美疲劳。只是这些手机依然没有令人心中一沉,眼前一黑。我不清 楚使用者为什么一定要换一个操作系统而后快。我有许多朋友都不喜欢微软这家公司,但是丝毫没有阻挡他们使用Windows和Office。从公司的角度上 看,使用这些后继者替代已有的Android,永远是羊儿有羊儿的道理,狼儿有狼儿的道理。只是我不清楚这些道理来自何方。

PC时代确是残阳似血,手持移动未必是旭日初升。在相当多人的心目中,智能手机操作系统这场游戏不是开始,而是结束。当针对某个应用的生态系统搭建 完毕后,市场上只有几个真正的Player,如PC时代的Wintel联盟,智能手机/Tablet时代的Google/Apple/ARM。在可以预见 的未来,目前处于智能手机操作系统领域的几个弄潮儿,会相互争斗,更多的只是经历PC帝国经历过的波澜不惊,花开花谢,潮起潮落。

无论是iOS,Android甚至其他后继者笑到最后,已经不再重要。这些操作系统已完成了各自的历史使命。相信最具智慧的Apple或是 Google的开发人员已不再继续关心着iOS和Android本身,或许他们早已发现未来需要解决的问题,超越了电子信息领域的已知的任何体系结构;超 越了Knuth提出的所有算法;或许他们率先体会到了自己的无知。依然在学习Google的三篇论文,想着用几秒钟完成1TB数据排序的人群无法体会到这 些苦楚。只是我们无法忽略一个事实,电子信息领域利用自身剧烈的“繁殖,重复,抄袭”所创造的辉煌正在成为过去。

身处这个领域的工程师们没有因此放弃努力,开始关注Cloud Computing。Cloud Computing的三个层次IaaS (Infrastructure as a Service),PaaS (Platform as a Service)和SaaS (Software as a Service),已是耳熟能详的概念。Cloud Computing的持续推进,使Cloud OS和Cloud Service逐步成为现实。IaaS如火如荼的重复建设延缓了Intel的衰老。SaaS可能是将来的主流,虽然目前没有太多成型的产品。

许多人以为未来的Cloud OS将等同于PaaS级别的API集合。一时间这类API的建设迅速成为热点。电子信息领域的设备提供商,无论是来自电信,还是IT领域,无不趋之若鹜。 这些昔日的王者,这些基础设施提供者,突然发现,他们一夜之间失去了全部内容。面对这场基础设置几乎免费,依靠着各类服务获取盈利的游戏,他们失去了将 来。直接想到的还是做一个操作系统,只是更加广义一些。


不仅是别离了乔布斯的苹果,甚至是Google,几无创新。Google眼镜和iWatch延续着电子信息领域的近亲繁殖。这些设备比手机更小一 点,更加接近身体。Google眼镜即将面试,Google一直采用透明化技术开发策略,这个项目并不保密。即将发布的iWatch,无论形态如何,功能 如何,都不再是乔布斯的iWatch了。

我阅读过许多评价iWatch的文章。这个离人体皮肤最近的设备,可以触摸脉搏,倾听内心深处的设备,依然有人关心这个设备使用什么操作系统,屏幕 大小有多大,能不能收发邮件,有没有iPhone的部分功能。我们始终在罗列Feature。我们始终在抄袭自己。我们蒙上了自己的双眼。我们的思想也许 受年轮的牵引而前行,骨子里流淌的依然还是PC时代落幕前所注入的鲜血。很多即将发布的产品,还没有开始,已宣告结束。

在我们所处的电子信息领域,目前所看到更多的就是结束。新生事物的开始与结束周期已经短到了我们不堪重负。有时不得不冷静思考,为什么我们所有的创 新离开了所谓IP的保护伞变得如此不堪一击,为什么我们所谓的创新会被抄袭得如此轻松。电子信息领域在长达几十年的发展历程中,从最初的席卷天下,到至今 最伟大的创新,始终没有逃脱近亲繁殖的影子。身处这个领域的每一个人都有这些创新的原始基因,任何一个所谓的抄袭者不过是在抄袭自己罢了。只是我们已经没 有剩下什么可以继续抄袭了。

在此前长达三十多年的时间里,电子信息领域始终引领整个世界持续向前,此刻终于放慢了脚步。在不远的将来,其他行业将逐步渗透到我们所在的这个领 域。来自电子信息领域内部的近亲繁殖,所出现的发明与创造将逐步脱去色彩。无论是此前的PC时代,还是近期出现的移动互联时代,已在悄然落幕。

电子信息领域真正的财富,是在漫长的统治期间,所积累的明显多于其他行业的人才。至今这个领域所蕴含的能量已无法提供更多的空间,在不远的将来,这 些人将利用在电子信息领域获得的利器,向上探索宇宙,向下了解我们的星球,向内心深处了解人类的健康,还有更加深远广袤的领域,在延伸电子信息领域边界的 过程中,确定电子信息领域应有的边界,一个跨领域的差异化与定制化时代正在悄然来临。




, ,

int *p[10] 指针数组:指向指针的数组,数组的元素是指针
int (*p)[10] 数组指针:指向数组的指针,就是一个指针而已,只不过指向的内容比较特别

int *p[10];
for(int i = 0; i < 10; ++i)
p[i] = new int;
*p[i] = i;
for(int i = 0; i < 10; ++i) {
std::cout << *p[i] << std::endl;
delete[] p[i];
int (*p2)[10];
int arr[2][10];
p2 = &arr[1];
for(int i = 0; i < 10; ++i) {
(*p2)[i] = i;
for(int i = 0; i < 10; ++i) {
std::cout << (*p2)[i] << std::endl;