October 15, 2014

New $20 Republic Wireless Referral Discount

Update 10/17/2014: Moto E is also eligible for $20 referral discount. However, the current referral program will be over on 10/31/2014. No information yet about when the referral program will be reinstated after 10/31/2014.

Update 10/15/2014: Moto E for $99 is now available at Republic Wireless.

Update 9/17/2014: Just got an email and Republic Wireless is going to roll out Moto E for $99 in October. No information about the plan options on this new phone yet, but since it is a 3G-only phone (no LTE), it is expected that the available plan options would be Options 1, 2, or 3 (the same as 3G-only Moto G). Moto E is a budget phone. For a simple comparison of Moto X, Moto E, and Moto G, check here.

Update 9/10/2014: Republic Wireless changed its roaming data cap to 25MB/month and with reduced speeds for Moto X and Moto G users. Motorola DEFY XT users still have the old 100MB/month cap but with reduced speeds. Check details here.

I just received an email today from Republic Wireless that the new referral program is now active.

Any new user of Republic Wireless signing up through a current user’s referral link gets $20 credit immediately. The current user will get $20 credit if the new user remains in Republic Wireless for 30 days. This “Give $20, Get $20” referral program (see also FAQ) replaces the discontinued “Give $19, Get $19” referral program.

Here is my referral link, if anyone wants to benefit from the referral discount: http://rwshar.es/besQr (You need to order the phone through this link to get $20 credit).

Please note that $20 referral credit is limited time offer. Republic Wireless may change or pull off the offer any time.

Why Republic Wireless?

Why may you want to use Republic Wireless as your cell phone service? The biggest point is low plan costs.

When Republic Wireless debuted, it received rave news coverage. It’s really affordable! It is possible for Republic Wireless to offer so affordable plans because the phones use Wi-Fi for voice calls (and text messages) if Wi-Fi is available.

New users of Republic Wireless have the following options for plan/phone:

Plan Option Monthly Cost Features Phones Talk Minutes Text Messages Data
1 $5 Wi-Fi Only Moto X $299; Moto G $149;
Moto E $99
Unlimited on Wi-Fi;
None on Cellular
Unlimited on Wi-Fi;
None on Cellular
Unlimited on Wi-Fi;
None on Cellular
2 $10 Wi-Fi+Cell
Talk & Text
Moto X $299; Moto G $149;
Moto E $99
Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
None on Cellular
3 $25 Wi-Fi + Cell (3G)
Talk, Text & Data
Moto X $299;
Moto G $149;
Moto E $99
Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
Unlimited* on Cellular 3G
4 $40 Wi-Fi + Cell (4G/LTE)
Talk, Text & Data
Moto X $299 Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
Unlimited on Cellular
Unlimited on Wi-Fi;
Unlimited* on Cellular 4G/LTE

New users can order either Moto X ($299) or Moto G ($149).

Republic Wireless services are very flexible, more like prepaid plans; there is no contract, and you can change between plans almost any time, up to 2 times per month with Republic Wireless. This is a big plus given the four available options. When your needs change, you can change your plan options temporarily or permanently. For example, you may start with Option 2, and if you find you must have some data access outside on the move or in the wild, you can switch to Option 3. If you find that is not fast enough for your needs, further switch to Option 4. When you travel overseas for a few months, where no cellular service for your phone anyway, you can switch to Option 1, and still remain connected to your buddies as long as you have Wi-Fi.

Unlimited Data

The new plans with unlimited cellular data has some fine text now:

*Our Terms of Service permit us to reduce your speed for a billing period if you exceed 5GB of data while using cell during the billing period. We also give you a break and will forgive you for exceeding 5GB of data once every 6 months! See our Terms of Service for more details.

The Republic Wireless Terms of Service 19(b)Your Service Plan may include limitations on Your Usage:

…cellular network data speeds may be reduced from full speeds otherwise applicable under Your Service Plan for the remainder of a billing period if your monthly cellular data Usage exceeds either (i) 5GB of cellular data Usage (excluding roaming), or (ii) 100MB of roaming cellular data Usage more than once in any six (6) month period.  If, in the prior six (6) months, Your cellular data Usage has not exceeded the limitation of either clause (i) or (ii) of the preceding sentence, You will be granted an additional 5GB of cellular data Usage (excluding roaming) and an additional 100MB of roaming cellular data Usage before the foregoing speed reductions apply.

This is my understanding:

  • You can use unlimited cellular data for no extra charge;
  • There are occasions that Republic Wireless may reduce your cellular data speeds:
    • If you never use more than 5GB data or 25MB roaming data in any billing month, your data speeds are full;
    • If you use 5GB data or 25MB roaming data in the middle of a month:
      • If you have not used more than 5GB data or 25MB roaming data in any of past 6 months, you can continue to use another 5GB data and 25MB roaming data (totaling 10GB/50MB for the month) at full speeds. Beyond 10GB/50MB, your data speeds can be reduced for the rest of billing month;
      • If you have used more than 5GB data or 25MB roaming data in any of past 6 months, your data speeds can be reduced for the rest of billing month.

Republic Wireless is a Mobile Virtual Network Operator (MVNO) and uses Sprint cellular networks. Therefore, reduced speeds basically mean no more than CDMA 1xRTT speeds, up to 144kbps. Anyone still remembers getting online using a dial-up modem? CDMA 1xRTT is like 2~3x of typical dial-up (56kbps). This might be enough for textual emails, instant messaging/chatting, browsing and so on, but probably too slow for content-rich web sites with images.

Given that most people are covered by Wi-Fi for a significant portion of the day, as Republic Wireless is really for these customers, it is rare that 5GB/10GB fast cellular data is a problem for them. I have never had a chance to even get close to that “fast cap” in the past 1.5 years. Even if one goes beyond that, the slower basic cellular data is still there for no extra charge. This is affordable peace of mind that we cannot get from other big name carriers. I think such limitations are reasonable to contain the operating costs. And I really hope people cherish what Republic Wireless offers, and not abuse its cellular voice and data (use as much Wi-Fi as possible), such that Republic Wireless can continue to exist to provide affordable services.

Update: Official Cell Data Limitations page at Republic Wireless.

History

For more history of the referral program and plan changes of Republic Wireless, see my previous post.

October 10, 2014

SFINAE To Check Existence of Member Type, Variable or Function

Introduction

SFINAE (Substitution Failure Is Not An Error) allows C++ compiler to silently ignore invalid instantiation attempts in function overload resolution involving function templates, instead of resulting in errors. This is often used to selectively choose desired behavior at compile time by template programmers.

Check Existence of Member Type

This is an example to check if a class has a specific member type named Type:

template<class T>
class has_member_type_Type
{
    struct big { char a[2]; };
    template<class C> static big  probe(typename C::Type*); // match here if type T::Type exists
    template<class C> static char probe(...);
public:
    static const bool value = sizeof(probe<T>(nullptr)) > 1;  
};

struct Foo
{
    using Type = int;
};

struct Bar
{
};

struct Gea
{
    int Type;       // member variable, not member type
};

struct Kye
{
    void Type();    // member function, not member type
};

int main() 
{
    static_assert(has_member_type_Type<Foo>::value, "");
    static_assert(!has_member_type_Type<Bar>::value, "");
    static_assert(!has_member_type_Type<Gea>::value, "");
    static_assert(!has_member_type_Type<Kye>::value, "");
    static_assert(!has_member_type_Type<int>::value, "");
    return 0;
}

In class template has_member_type_Type, The second probe function, probe(...) has the least rank in overload resolution. The first probe function, probe(typename C::Type*) is valid and overtakes the second probe function, only when C (in fact T) has a member type Type. If Type is not a type, for example, if it is a variable or function, it is correctly differentiated.

Check Existence of Member Variable or Function

Modifying the example above a little bit, it is easy to get a class template that checks if a class has the named member variable or function:

template<class T>
class has_member_Member
{
    struct big { char a[2]; };
    template<class C> static big  probe(decltype(&C::Member)); // match here if T::Member exists
    template<class C> static char probe(...);
public:
    static const bool value = sizeof(probe<T>(nullptr)) > 1;  
};

struct Foo
{
    int Member;
};

struct Bar
{
    void Member();
};

struct Woo
{
    static int Member;
};

struct Doo
{
    static void Member();
};

struct Gea
{
};

struct Kye
{
    using Member = int;
};

int main() 
{
    static_assert(has_member_Member<Foo>::value, "");
    static_assert(has_member_Member<Bar>::value, "");
    static_assert(has_member_Member<Woo>::value, "");
    static_assert(has_member_Member<Doo>::value, "");
    static_assert(!has_member_Member<Gea>::value, "");
    static_assert(!has_member_Member<Kye>::value, "");
    static_assert(!has_member_Member<int>::value, "");
    return 0;
}

The first probe function expects a parameter of pointer to T::Member. This is only possible if Member is a member variable or member function. It also works for static member variable or function. It works as expected if Member is a member type or does not exist.

Better Reuse

Notice that the class templates has_member_type_Type and has_member_Member are hard-wired with the names to be checked. They basically not reusable if we want to check other member types, variables or functions.

Luckily, there are not a lot of appearances of the specific names in the class template definitions. We can use macros to wrap them up for better reuse:

// checker class templates
#define DEFINE_MEMBER_TYPE_CHECKER(MemberType) \
    namespace { \
        template<class T> class has_member_type_##MemberType \
        { \
            struct big { char a[2]; }; \
            template<class C> static big  probe(typename C::MemberType*); \
            template<class C> static char probe(...); \
        public: \
            static const bool value = sizeof(probe<T>(nullptr)) > 1; \
        }; \
    }

#define DEFINE_MEMBER_CHECKER(Member)   \
    namespace { \
        template<class T> class has_member_##Member \
        { \
            struct big { char a[2]; }; \
            template<class C> static big  probe(decltype(&C::Member)); \
            template<class C> static char probe(...); \
        public: \
            static const bool value = sizeof(probe<T>(nullptr)) > 1; \
        }; \
    }

// checking macros
#define HAS_MEMBER_TYPE(Class, MemberType)  has_member_type_##MemberType<Class>::value
#define HAS_MEMBER(Class, Member)           has_member_##Member<Class>::value

It provides two sets of macros. The DEFINE_MEMBER_XXXXX macros are to setup for checking the member of the given name. The HAS_MEMBER_XXXXX macros are used to check if Class has that MemberType or Member.

Notice that before using HAS_MEMBER_XXXXX for a specific MemberType or Member, be sure to have a corresponding DEFINE_MEMBER_XXXXX_CHECKER invocation such that the underlying class template is ready.

HAS_MEMBER_XXXXX expands into a compile time bool constant, for example, it can be used in static_assert and as template argument.

Usage Example

Below is an example of using the macros above to check existence of member types and variables or functions:

// 1. define the checkers
DEFINE_MEMBER_TYPE_CHECKER(MemberType)  // To check member type: MemberType
DEFINE_MEMBER_CHECKER(Member)           // To check member variable or function named Member

// 2. use the HAS_MEMBER_XXXXX macros

struct Foo {
    using MemberType = int;
};

struct Bar {
    double Member;
};

struct Roa {
    void Member();
};

struct Gea {
    static int Member;
};

struct Lye {
    static void Member();
};

int main() {
    static_assert(HAS_MEMBER_TYPE(Foo, MemberType), "");
    static_assert(!HAS_MEMBER_TYPE(Bar, MemberType), "");
    static_assert(!HAS_MEMBER_TYPE(int, MemberType), "");

    static_assert(HAS_MEMBER(Bar, Member), "");
    static_assert(HAS_MEMBER(Roa, Member), "");
    static_assert(HAS_MEMBER(Gea, Member), "");
    static_assert(HAS_MEMBER(Lye, Member), "");
    static_assert(!HAS_MEMBER(Foo, Member), "");
    static_assert(!HAS_MEMBER(int, Member), "");

    return 0;
}

The same idea is also used the much more comprehensive boost TTI (Type Traits Introspection) library.

October 4, 2014

Microsoft Wheel Mouse Optical: Fix Button Click Problems

I have two of Microsoft Wheel Mouse Optical. I have used them for maybe more than 10 years. They are not fancy, but they have been very reliable for so many years. However, recently both of them have behaved strangely. One did not respond when I clicked the left mouse button. The other one often double clicked while I only clicked the left button once. This is a picture of one of them:

image

They look a bit old and don’t worth much. In fact, repairing them may not worth the time either. However, they are electronic waste and I don’t bother to go somewhere just to recycle them. So I think I should repair them!

Searching over the internet, I found this nice article: Repair mouse with double click problem. It is about a different Logitech mouse, but it helps a lot for me to open the case. The Microsoft mouse is in fact harder to open because it has two screws and two plastic tabs under the sticky pads. The two plastic tabs needed to be pushed hard while I pried the side of the mouse.

This was how the interior looked like in the Microsoft mouse after I cleaned the dust:

image

I have highlighted the faulty switch on the circuit board corresponding to the left mouse button. To take out the smaller circuit board and reach the faulty button, I needed to remove the wheel first. Lifting the wheel axle from the plastic holding:

image

image

Removing the two screws on the bigger circuit board:

image

The smaller circuit board is held to the back case of mouse with three half-transparent plastic tabs, use small flat head screw driver to carefully pry them and lift the board:

image

It is easy to see that, unlike that of the Logitech mouse, the switch component in the Microsoft mouse is monolithic and probably impossible to repair if its internals go wrong or unreliable.

I looked around and noticed the third switch (in blue circle) other than the left (in red circle) and right button switches:

image

That’s the middle button switch. I use the middle wheel of the mouse often to scroll pages, but I have almost never used the middle button clicks. Obviously, the left button switch has been heavily used for 10+ years and has worn out, but the middle button switch has been virtually unused in so many years. I could swap the left button switch and middle button switch and it does not hurt anything to me!

I took out my soldering iron. Liana and Colin helped to hold the circuit boards (with a great deal of caution as the iron was really hot) and I removed the switches from the boards. They looked exactly the same so I was very careful to put the good middle button switch aside. This was one of the switches:

image

Then I swap the switches and soldered them back to the circuit board. Connect it to the computer, and verify the left button switch works:

image

I then closed the cover, tightened screws and re-attach the sticky pads. The switches from middle button should be strong enough to work for quite some years, maybe until Gesture UI replaces the mouse!

September 25, 2014

Google Test Macros and Avoid Taking Reference of Static Const Integral Data Member of Class

Background

C++ allows a static const integral data member of a class to be initialized inline in a class without a separate definition in a source code file, as long as the no code takes the address or reference of that data member. This is an example:

struct Foo
{
    static const int COUNT = 100;
};

int main(int argc, char** argv) 
{
    return Foo::COUNT==100 ? 0 : -1;
}

In this example, no actual variable is created in memory for Foo::COUNT, because the compiler is able to expand all expressions involving it with its actual value 100 as immediate number. That’s why no definition is needed for Foo::COUNT.

The example below should not work:

struct Foo
{
    static const int COUNT = 100;
};

int main(int argc, char** argv) 
{
    const int& c = Foo::COUNT; // reference taken
    return c==100 ? 0 : -1;
}

When the reference of Foo::COUNT is taken, Foo::COUNT must exist in memory, otherwise c would not be able to reference anything literally. The compiler should spit an error like undefined reference to Foo::COUNT. Some compilers may be more tolerant, but the non-portable behavior should not be counted on. The corrected version is as follows:

struct Foo
{
    static const int COUNT = 100;
};

const int Foo::COUNT; // definition

int main(int argc, char** argv) 
{
    const int& c = Foo::COUNT; // reference taken
    return c==100 ? 0 : -1;
}

As I am biased on favoring header file only libraries, a separation definition is something I want to avoid. Therefore, I would avoid taking reference or address of such static const data members so the only thing I need to maintain is the class definition in the header file.

Google Test Macros

Since I happen to use Google Test (gtest 1.7), I have some code that looks like below:

#include <gtest/gtest.h>

struct Foo
{
    static const int COUNT = 100;
};

TEST(test, case1)
{
    int count = 100;
    EXPECT_EQ(Foo::COUNT, count);
}

Basically, I want to make sure that some calculated count is expected to be the same as Foo::COUNT.

The code looks totally innocent. The test builds and runs without any problem with Visual Studio 2013. But if I feed it to GCC 4.7 (or 4.8), it would spit a link error undefined reference to ‘Foo::COUNT’...recipe for target failed:

Linking CXX executable test
test.cpp.o:test.cpp:function test_case1_Test::TestBody(): error: undefined reference to 'Foo::COUNT'
collect2.exe: error: ld returned 1 exit status
build.make:789: recipe for target 'test' failed

Obviously, the Google Test test macro EXPECT_EQ would take the reference of the first argument in effect, and cause this error. Of course, it was not this obvious and simple in real code, because it was buried in big pile of other code when I found this, but this was the reason.

Digging up some gtest code and it finally arrives at this template class EqHelper:

template <bool lhs_is_null_literal>
class EqHelper {
 public:
  // This templatized version is for the general case.
  template <typename T1, typename T2>
  static AssertionResult Compare(const char* expected_expression,
                                 const char* actual_expression,
                                 const T1& expected,
                                 const T2& actual) {
    return CmpHelperEQ(expected_expression, actual_expression, expected,
                       actual);
  }

  // With this overloaded version, we allow anonymous enums to be used
  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
  // enums can be implicitly cast to BiggestInt.
  //
  // Even though its body looks the same as the above version, we
  // cannot merge the two, as it will make anonymous enums unhappy.
  static AssertionResult Compare(const char* expected_expression,
                                 const char* actual_expression,
                                 BiggestInt expected,
                                 BiggestInt actual) {
    return CmpHelperEQ(expected_expression, actual_expression, expected,
                       actual);
  }
};

Our Foo::COUNT would end up as expected parameter in the Compare function. There are two overloaded Compare functions, where the first one takes expected as const T1&, and the second one BiggestInt. BiggestInt is a typedef of long long. It’s simple to see that an int would resolve to the first overload rather than the second, therefore a reference is taken! See this example:

#include <iostream>

template<typename T>
void foo(const T& a)
{
    std::cout << "foo T" << std::endl;
}

void foo(long long a)
{
    std::cout << "foo long long" << std::endl;
}

enum { AA = 100 };
enum Color : int { Red };
enum class Shape : int { Square };

int main(int argc, char** argv)
{
    int a = 100;
    foo(a);             // foo T
    foo(AA);            // foo T
    foo(Red);           // foo T
    foo(Shape::Square); // foo T
	return 0;
}

Not only an int, but also all enums (named or anonymous) would resolve to the overloaded function template instead of the function with specific long long parameter. Obviously, the gtest comment stating that gcc 4 would match an anonymous enum to the second overload is no longer true.

Anyway, now it’s clear that EXPECT_EQ would take the arguments as const reference, and that’s the reason that static const data member initialized in class definition would yield undefined reference error at link time. Not only EXPECT_EQ, but also a lot of other test macros in gtest would have the same behavior.

Workarounds

Again I have no motivation to add C++ source files to house the static const data member definitions to my header only libraries, just to please these gtest macros. Let’s look at some workarounds.

  • Use an anonymous enum instead of static const data member in class. For example, this works:
struct Foo
{
    enum { COUNT = 100 };
};

TEST(test, case1)
{
    int count = 100;
    EXPECT_EQ(Foo::COUNT, count);
}

The problem is that COUNT is probably no longer of my desired type. What if I need to access the data member with an explicit type? For example:

enum class BarType
{
    wood,
    metal
};

template<BarType bar_>
struct Foo
{
    static const BarType bar = bar_;
};

I want to access Foo::bar with a strong type BarType. If I use an anonymous enum for bar in Foo, I lose bar’s original type, and that is not acceptable.

  • Use a different test macro that does not take reference. For example, I can use EXPECT_TRUE instead of EXPECT_EQ for the same purpose:
    //EXPECT_EQ(Foo::COUNT, count);
    EXPECT_TRUE(Foo::COUNT==count);

Almost all tests can be replaced with EXPECT_TRUE or EXPECT_FALSE. This works, but when the test fails, the error message is kind of non-ideal:

C:\temp\test.cpp(22): error : Value of: Foo::COUNT==count
    Actual: false
  Expected: true

While in the original test EXPECT_EQ(Foo::COUNT, count), if it fails it would tell me the exact expected and actual values, and that helps me to figure out how it went wrong:

C:\temp\test.cpp(22): error : Value of: count
    Actual: 101
  Expected: Foo::COUNT
  Which is: 100
  • Create a copy and pass the copy to the test macro. Do not pass the static const member data directly to the test macro. Create a temporary copy and pass that. For example:
    int count = 101;
    //EXPECT_EQ(Foo::COUNT, count);
    //EXPECT_TRUE(Foo::COUNT==count);
    EXPECT_EQ(int(Foo::COUNT), count);

Here I pass a temporary int initialized with Foo::COUNT to EXPECT_EQ. This builds fine, and if the test fails, the error message is much better than that of EXPECT_TRUE:

C:\temp\test.cpp(22): error : Value of: count
    Actual: 101
  Expected: int(Foo::COUNT)
  Which is: 100

Since the static const data members without separate definitions are integral types only, creating a temporary copy is virtually no cost. Other than the little annoyance of typing the explicit type of the variable, this workaround is my best choice so far.

September 16, 2014

Storage Class and Static

What storage class affects

In C and C++, the storage class of a variable, function parameter or function determines certain properties of the entity, including:

  • linkage/visibility
    • no linkage: the entity can only be referenced in the same scope and not from anywhere else via names.
    • internal linkage: the entity can only be referenced via names in the same translation unit (roughly the same source file).
    • external linkage: the entity can be referenced via names across translation units and through the whole program.
  • storage duration/lifetime
    • static: the storage is maintained throughout program run time. Only one instance exists for the whole program, i.e., per-process.
    • automatic: the storage is maintained only during the execution of the block where the entity is defined. Each entrance/exit of the block of each thread allocates/deallocates a new instance. This basically means it is on the stack, and per-invocation.
    • thread: Each thread has an exclusive instance of the variable by name. The variable is allocated/initialized before the thread accesses it (may be omitted if not used by the thread), and destroyed (if initialized) when the thread ends. This corresponds to thread_local storage class, and is per-thread. New in C++11.

Additionally, the storage and implicit initial value of a variable or function parameter is affected by the storage class.

  • storage
    • memory: the entity is stored in memory. The compiler may be able to optimize and use registers to store the entity.
    • register: the entity is stored in a register. If the compiler is not able to put it in a register, it is stored in memory, including when register file is used up, or address of the entity is taken, etc.
  • implicit initial value
    • zero initialized: if not initialized explicitly, the entity is filled with bytes of zeros when it comes into life.
    • indeterminate: if not initialized explicitly, the entity uses an indeterminate default value (whatever byte values in that memory location).

Due to weak differentiation of memory/register storage and deprecation of register storage class, nowadays virtually all variables and function parameters are of memory storage.

The implicit initial value of a variable can also be considered to be associated with storage duration, rather than directly with storage class. A simple rule is that variable with static duration is zero initialized implicitly, and variable with automatic duration is indeterminate.

Storage class specifiers

When the default storage class is not desired, you can use an explicit storage class specifier to modify the entity’s storage class:

  • storage class specifier
    • (default): when you do not specify any storage class specifier.
    • auto: for local variables in C++98. In C++11 it is no longer a storage class modifier, and is instead used with automatic type deduction from initializer.
    • register: intention to put a local variable or function parameter in a register. The compiler may not honor that, for example, when register file is used up, or address is taken from the entity. On the other hand, an automatic-duration local variable or function parameter, even without a register specifier, may be put in a register by the compiler with optimization. Therefore, register is less often used today, and is in fact deprecated in C++11.
    • extern: intention to declare an entity with external linkage.
    • static: it means different things, for static duration, internal linkage, or member available in a class without instantiating an instance.
    • thread_local: this may only be added to a variable that has static duration, such that the variable now has the thread duration. It refines the duration such that each thread has its own copy, rather than using the same global copy. It does not affect linkage.
    • mutable: the keyword is a storage class specifier in C++ language syntax but it does not affect linkage or storage duration. It is used to make a class data member modifiable even when the class object is declared const.  C++ only.

The Table

Not all storage class specifiers can be used against an entity. For example, a function can only have either extern (default) or static storage class, and they only affect the linkage of a function, because the function’s storage, implicit initial value and duration are obvious. Possible storage class specifiers on different entities in various scopes are listed in the table below. Each entity may appear in the different scopes. All other combinations are invalid.

  • scope
    • global = global or in a namespace
    • block = block or local
    • class = in a class or struct, C++ only

entity

scope

storage class specifier

linkage / visibility

duration / lifetime

storage

implicit initial value

Notes

variable global (default) external static memory 0 = extern
variable global extern external, internal* static memory 0  
variable global thread_local extern external, internal* thread memory 0  
variable global thread_local external thread memory 0 = thread_local extern
variable global static internal static memory 0 anonymous namespace^
variable global thread_local static internal thread memory 0 anonymous namespace^
variable block (default) no automatic memory indeterminate definition
variable block auto no automatic memory indeterminate different use in C++11
variable block register no automatic register indeterminate definition. deprecated
variable block extern external, internal** static** memory - declaration only
variable block thread_local extern external, internal** thread memory - declaration only
variable block static no static memory 0 definition, C++11 safe init
variable block thread_local static no thread memory 0 definition
variable class (default) no automatic memory indeterminate = auto/register
variable class static external static memory 0 needs separate definition
variable class thread_local static external thread memory 0 needs separate definition
function parameter N/A (default) no automatic memory - = auto/register
function parameter N/A register no automatic register - deprecated
function global (default) external, internal* - - - definition/declaration only
function global extern external, internal* - - - declaration only
function global static internal - - - anonymous namespace^
function block (default) external, internal* - - - declaration only
function block extern external, internal* - - - declaration only
function class (default) external - - -  
function class static external - - - non-instance

*: For declaration only, even though a variable or function is declared for external linkage, it can have internal linkage if the name was previously declared with internal linkage in the same translation unit (external linkage collapses to accidental internal linkage). This applies to global/block variable/function declarations.

**: Even though a variable is declared for external linkage in a block scope, it can refer to a variable in an enclosing scope, which has no linkage. See an example from MSDN. This is a special case of external linkage collapsing to no linkage. This is impossible for a function declaration in block scope, because a referred function cannot be defined in (enclosing) block scope.

^: In C++, static global variable and function are discouraged, and you can achieve the same effect with anonymous namespace., with better superiority.

Static

In C and C++, static is an overloaded word with many different meanings. It has the following uses:

  • 1) The static storage duration of a variable. This means after the variable is initialized, there is exactly one copy of it for the whole program and all threads, and the value is maintained until the program finishes. Be careful about thread-safety of these variables! They include:
    • All variables in global or other namespaces, static or not.
    • Block-scope static variables
    • Class-scope static variables
  • 2) The static storage class specifier keyword.
    • 2.a) A static global/namespace variable. It has internal linkage and static duration. Please use anonymous namespace instead.
    • 2.b) A static global/namespace function. It has internal linkage. Please use anonymous namespace instead.
    • 2.c) A static block scope variable. It has no linkage (accessible only in the defining block scope) and static duration. Unlike C++98, C++11 guarantees the initialization of the variable is thread-safe. But thread safety of subsequent accesses has to be done properly by the programmer.
    • 2.d) A static member variable in a class. It has external linkage and static duration. Unlike other member variables (each instances of the class would have its own copies, i.e., per-instance), a static member variable is per-class. It needs separate definition in a translation unit (unless it is integral static const member variable, which can be defined and initialized in the class). It is similar to a variable in a namespace, subject to class access control (public, protected, private).
    • 2.e) A static member function in a class. It has external linkage. Similar to static member variable, you do not need an instance to call a static member function. It is similar to a variable in a namespace, subject to class access control (public, protected, private).

References

http://en.cppreference.com/w/cpp/language/storage_duration

http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7a.doc%2Flanguage%2Fref%2Fclrc03sc03.htm

http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx

http://gaubuali.wordpress.com/linkage-in-c-and-c/

September 13, 2014

One-Click Root Motorola DEFY XT (Republic Wireless)

[memo]

See http://www.androidpolice.com/2013/01/28/exclusive-one-click-root-for-the-republic-wireless-motorola-defy-xt-single-and-dual-band-with-the-newest-ota-1_65k_1027-or-older/

Just download Cyanide.apk to the phone and run it. Use some patience. After two reboots, the phone is rooted. After the second reboot, SuperSU will be installed to manage the root access on the phone, for example, granting apps the root access.

From there, Link2SD can be installed to extend the limited internal memory for installing apps (see a previous post).

September 12, 2014

昂立莱辅酶Q10

最近有国内亲戚委托我在美国购买昂立莱牌子的辅酶Q10和深海鱼油。在网上做了简单的搜索,找到了其官方网站:http://www.onlife.net.cn/。但是稍微看了看该网站,就让人疑窦丛生。

可疑的品牌故事

该网站首页就有一个品牌故事,具体见http://www.onlife.net.cn/ylcqy.asp

昂立莱起源

有一个叫斯蒂文·约翰年轻人经过长途跋涉到异地赶考,途遇 暴雨,流落在美国加利福利亚的一个村庄,因饥寒交迫,体力 不支,倒在一家农门前,昏迷不醒,被人救起。
斯蒂文·约翰醒来时,发现自己已经躺在温暖的小屋内,虽然 小屋非常简陋,但非常温馨,小屋的主人是老俩口,年老体弱, 他们拖着带病的身躯救了他,尽管当时没有好的医疗水平,但 斯蒂文· 约翰还是得了农户家悉心的照顾,老人们虽然家境贫 寒,他们非常恩爱,斯蒂文·约翰在农户家养病,时常被他们的 爱所感染,由于斯蒂文·约翰在农户家得到悉心照料,斯蒂文很 快痊愈,后来斯蒂文考上了美国著名的哈佛大学生物工程学院, 求学期间,因为时空阻隔,斯蒂文没办法和农户家保持经常的 联系,后来听说斯蒂文住过的那个村庄发生瘟疫,和他关系最 好的养母在这场瘟疫中丧生,这件事刺激了斯蒂文,斯蒂文决 定中途转攻生物营养学科,致力于增强人们体质、抵抗疾病肆 虐的研究,由于斯蒂文天资聪颖和勤奋努力,终于在营养学领 域有了卓越成就,成为美国营养学领域的权威科学家。
为了表彰他在营养学领域的贡献,哈佛大学生物工程学院还专 门成立了"斯蒂文·约翰基金会",出于对村民的感恩,让" 爱"传递下去,由斯蒂文博士提议, 斯蒂文·约翰基金会从20 世纪七十年代开始每年都会划拨专项资金,支持斯蒂文·约翰第 二故乡的医疗福利事业,由于医疗福利推广到位,村庄里的人 从此过上了健康幸福的生活,为了感谢斯蒂文·约翰的施恩,村 民们给斯蒂文·约翰他取名叫昂力莱——on life of love(在 爱的生命里),让以斯蒂文·约翰(昂力莱)爱的精神永续传承。

这么一段小短文就有一些小文法问题,比如“倒在一家农门前”,“村民们给斯蒂文·约翰取名叫昂力莱”, 还有每个段落不管多长都只有一个句子等等,不像是一个有实力的公司网站上的东西。

其次,该故事逻辑很不合理。

  • 经过长途跋涉后,中途到达西海岸的加州,而目的地是在美国东北角的麻州的哈佛大学,这斯蒂文同学到底是从哪里出发的?
  • 悉心照料了几天,就变成了养母
  • 他的“养母”在瘟疫中丧生,斯蒂文同学受到刺激,他应该中途转攻直接对付瘟疫的医学才对。转攻营养学对瘟疫有啥直接效果?营养好恐怕也挡不住瘟疫。
  • “村民们给他取名叫on life of love”。那个on是表达斯蒂文同学的状态吗?反正看着多余。叫life of love也不合理,又不大写,又是常见字眼,村民日常说话还用不用这两个字表示他们原来的意思。没听说过这么给人取名的。

最重要的是,这个故事没有任何事实支撑。

  • 故事没有具体的时间和地点。
  • “后来听说斯蒂文住过的那个村庄发生瘟疫”。瘟疫特指在广大区域或全球多处传染的大型流行病(如果只局限于那个村庄,就谈不上瘟疫)。SARS,禽流感,埃博拉病毒等算是最近的瘟疫,虽然死亡人数远远比不上历史上鼠疫等瘟疫,但也名声大噪了。二十世纪在七十年代近前在加州发生的瘟疫,一定可以查得到,请问到底是哪一个?
  • 从故事中,可以知道斯蒂文同学显然在二十世纪七十年代之前就上过哈佛大学生物工程学院。但是,哈佛大学没有生物工程学院!
    • 目前的生物工程在哈佛大学甚至都不是一个系,而是工程与应用科学学院下的一个相当于系的Area。
    • 哈佛历史上有过生物化学系,生物化学和分子生物学系,生物系,细胞和发育生物学系,有机体与进化生物学系等,经过分分合合,现在哈佛有分子和细胞生物学系,以及有机体与进化生物学系(链接)。
    • 哪位哈佛的同学说说,到底曾经有没有生物工程学院?
  • 不存在的哈佛大学生物工程学院,如何专门成立斯蒂文·约翰基金会?
  • 就算哈佛大学有这个生物工程学院好了。斯蒂文同学中途弃之而去投奔哈佛大学营养学系,而且在营养学领域有了卓越成就。为了表彰他在营养学领域的贡献,为什么是哈佛大学生物工程学院,而不是哈佛大学营养学系,专门成立"斯蒂文·约翰基金会"?哈佛大学营养学系属于哈佛大学公共卫生学院,和工程与应用科学学院下的生物工程不是一个机构。
  • 斯蒂文·约翰,美国营养学领域的权威科学家,你在哪里,为什么连Google大神都看不到你?还有你的斯蒂文·约翰基金会,Google大神也看不到?唯一的相关链接,就是昂立莱网站。

综上所述,该故事看上去很励志,但是昂力莱应该拿出事实来,大家才会信服。

可疑的美国昂立莱品牌

根据昂力莱(中国)有限公司网页http://www.onlife.net.cn/onlife-info.asp

image

以及广州富诺生物科技有限公司介绍http://16888.qw168.com/

昂立莱带给您人生幸福健康和未来,昂力莱系列营养补充剂是美国昂立莱有限公司邀美国营养学研发中心研制出来的高科技产品,昂立莱依托强大的科研力量,专家团队营养补充研发技术全球领先,科学家们精心配比,反复研究,终结硕果,昂立莱产品分为三大系列三十多个品类,昂立莱系列营养补充剂国内分装选择与著名双GMP企业广东仙乐制药有限公司进行合作,国际化的无菌生产厂、一流的设备仪器、先进的生产工艺、苛刻的检查和审核流程,确保了昂立来的品质纯正。昂立莱所有产品均选用优质进口原料,符合美国FDA质量控制标准,昂力莱所有产品均严格按GMP标准生产,配比更科学,结构更合理,营养更充分,安全有保障,中国消费者可放心选用。

可以知道应该存在一个美国昂力莱有限公司(或者美国昂莱有限公司,我也不知道他们官方翻译都这么不认真,一会儿力,一会儿立)。通过搜索,却无法发现这个“美国营养保健知名品牌”昂力莱/昂立莱,相关搜索都是回到昂力莱(中国)有限公司和广州富诺。如果搜索Onlife,跟健康有关的也只有Onlife Health,这是一家位于美国田纳西州的健康咨询公司,不生产任何保健品或药品/原料。至于美国营养学研发中心,我没能找到关于该中心的任何信息。最接近的是美国农业部下属的儿童营养研究中心(Children’s Nutrition Research Center)。

如果昂力莱(中国)有限公司能够提供美国昂立莱有限公司以及美国营养学研发中心的有关信息,将有助于大家了解昂力莱品牌的强大。

可疑的产品宣传

昂力莱(中国)有限公司官方网站的辅酶Q10信息http://www.onlife.net.cn/productShow.asp?id=42

image

这个介绍非常简单。

如果搜索“昂力莱辅酶Q10”,马上就会到7度购保健品商城http://www.7dugo.com/goods-13.html

image

注意,7度购是昂力莱辅酶Q10的大陆唯一官方授权,因此我们相信7度购的产品宣传是获得昂力莱的首肯的。

image

抛开网页上其他声称的奇妙疗效,我们随便看看几处。这里说,“世界心血管健康研究中心”专业推荐,超过3项建议服用昂力莱辅酶Q10调理。

  • 首先,我没法找到“世界心血管健康研究中心”的任何信息,用英文搜索“World Cardiovascular Health Center”也没有结果。如果他们能够提供世界心血管健康研究中心的有关信息,我将不胜感激。
  • 即使存在“世界心血管健康研究中心”,他们也不是专业的心血管医生。心血管医生的专业建议是:心血管疾病有有效的治疗方法,如果你有心血管方面的疾病,请就医。他们绝不会建议你吃点辅酶Q10作为解决心血管健康问题的方案。辅酶Q10最多也只是辅助治疗。(来源:加州大学伯克利分校公共卫生学院:你能指望辅酶Q10吗?
  • 即使“世界心血管健康研究中心”真的专业推荐,也应该不会专门推荐昂力莱辅酶Q10。辅酶Q10是一种常规化合物,有已经测定的分子结构。换句话说,谁家生产的辅酶Q10都是一样的,并无机密可言。这个中心如果认为辅酶Q10对心血管疾病有用,也不需要专门推荐昂力莱牌子的。

image

这里看到,“中国心血管保健中心”也推荐昂力莱辅酶Q10。

  • 同样,我也找不到这个“中国心血管保健中心”(最接近的是卫生部下属的“国家心血管病中心”)。谁能提供“中国心血管保健中心”如何推荐昂力莱辅酶Q10的信息,我愿闻其详。
  • “结合神秘中医配方”,“效果超同类10倍以上”。上面已经说过了,辅酶Q10都一样,没什么神秘的。就算有什么神秘配方,比如加点人参啥的,那也和辅酶Q10没关系。“效果超同类10倍以上”,这个神奇了,大家都是结构一样的辅酶Q10,凭啥你的效果是其他产品的10倍以上?你怎么测出来的?其他厂商听了恐怕不高兴了。
  • “辅酶q10含量40mg/颗(最科学的摄入量)”。权威来源说,辅酶Q10的疗效研究经常自我矛盾,没有一致的结论,厂商声称的效果通常是夸大的,而且没人知道最合适的摄入量是多少

总结

根据维基百科,辅酶Q10确实在人体内营养物质转化为能量过程中起重要作用,而且抗氧化。人体可以合成辅酶Q10,也可以从食物中摄入。随着年龄增长,人体内辅酶Q10的水平会下降。某些疾病会导致人体内辅酶Q10的水平下降。但是,人体内辅酶Q10水平下降是生病的结果,而不是原因。通常认为,摄入辅酶Q10不能达到治病的目的。

在美国和中国,辅酶Q10都不是一种处方药,只能算是保健品。厂商不应该声称能治这个病那个病。生病的人应该去看医生,最好不要指望吃辅酶Q10能治病或有确切疗效。不过,研究表明,辅酶Q10的毒性很小,一天吃个1200mg也没事。所以你要是有那个钱,吃吃辅酶Q10试试看,应该也没什么明显的坏处。辅酶Q10在美国也是和一众维生素类保健品一起卖的。

当然,亲戚让在美国购买昂立莱牌子的辅酶Q10和深海鱼油,恐怕完不成任务了。

September 7, 2014

Remove Malware “Fast and Safe”

My wife tried to use her computer with her employer’s VPN. The VPN client did not work until she turned off Windows Firewall. I could have made the VPN client an exception in Windows Firewall earlier, but in 2 days when the firewall was off, her computer showed annoyances.

First of all, her Chrome browser started with an unfamiliar home page, not google.com that she had used. When she visited LinkedIn, there were extra blocks of fishy ads right in the LinkedIn web page. Google search also showed extra funny ad blocks. As contrast, Chrome on my computer does not have this problem.

I checked her Chrome settings, and found two strange extensions. The Chrome on my computer has only one Google Docs extension. I deleted the two extra extensions from her Chrome. After restarting, her Chrome worked fine.

I though it was done. But the next day she said, those annoyances came back to her Chrome again! And she found her Internet Explorer (IE) had the same problem! I went into Manage add-ons in IE, and found fishy add-ons like deal2x, saveas etc. They resided under hidden C:/ProgramData folder. Even running IE as Administrator would not allow me to delete these add-ons. They were rogue add-ons. Very likely, there could be something that would run automatically messing up the system.

A very well known tool to check what run automatically in Windows is Autoruns. This is a green application, just extract the files to a local folder, and run autoruns.exe. It revealed the IE add-ons. I tried to delete them from within Autoruns but it complained it could not find the files, although they were there. More importantly, it showed that AppInit was hooked up by fastandsafe.dll. Hooking up AppInit can hijack Windows API calls, and anything doing that is automatically suspicious. A simple Google search showed that Fast and Safe is malware.

One simple way to remove those stubborn malware is to reboot into Safe Mode of Windows. In this mode Windows loads minimal device drivers and runs least autorun programs, therefore the bad code does not get to run, and we can clean it. It’s a bit involved to boot into Safe Mode for Windows 8 or 8.1. After booting in Safe Mode, I ran Autoruns again, then deleted the AppInit and Internet Explorer entries, then went to C:\ProgramData and deleted those fishy subdirectories. I also deleted the Chrome extensions.

After rebooting, her computer has been normal. Of course, I make sure Windows Defender and Windows Firewall are enabled.

August 5, 2014

Return Value Optimization

Introduction

Return Value Optimization (RVO) is an important use of copy elision in C++. RVO is often used when a function returns a potentially big class object.

Although not part of the C++ standard, most calling conventions today for C++ functions returning a class object is more or less like this:

  • a. The caller provides enough uninitialized memory to hold the return object. Its address is passed as hidden first parameter to the function in addition to the parameters of the function.
  • b. The callee is responsible to construct the return object at the given address, and returns that address.
  • c. The caller access the address for the return value object. The object is an unnamed temporary.

Return Value Optimization (RVO) is about how the callee constructs the return object at the given address in step b) with minimal overhead.

The basic idea of RVO is to avoid creating a separate class object in the function implementation, by creating the object directly in the caller provided object memory. This is exactly using copy elision.

[Side note: If the returned value (an rvalue temporary) is used to initialize another object by the caller, a temporary object copy elision may be chained, i.e., the callee may directly construct on the final object.]

There are two types of RVOs: Unnamed Return Value Optimization (URVO) and Named Return Value Optimization (NRVO).

Unnamed Return Value Optimization

This is an example of Unnamed Return Value Optimization:

#include <iostream>

struct Foo
{
    Foo(int n) : num(n) {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
    int num;
};

Foo bar(bool ok)
{
    if (ok)
        return Foo(42); // URVO
    else
        return Foo(0);  // URVO
}

int main(int, char**)
{
    bar(true);
    return 0;
}

Notice that all the return paths must return an rvalue temporary object in URVO. With URVO, the temporary would be constructed directly on the return value object, and no copy/move construction is necessary. Even though this is a return statement, in fact it is temporary object copy elision.

In this example, both Debug and Release builds with my Visual Studio 2013 perform URVO and print nothing. If RVO is not performed, the copy constructor would be called and it should print Foo copy constructor called.

Named Return Value Optimization

This is an example of Named Return Value Optimization:

#include <iostream>

struct Foo
{
    Foo(int n) : num(n) {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
    int num;
};

Foo bar(bool ok)
{
    Foo a(0);
    if (ok)
    {
        a.num = 42;
        return a;   // NRVO: a
    }
    return a;       // NRVO: a
}

int main(int, char**)
{
    bar(true);
    return 0;
}

Notice that all the return paths must return the same local class object in NRVO, a, in this example. This allows the exact local object to collapse on the return value object, i.e., perform return value copy elision. For this example, Visual Studio 2013 performs NRVO in Release build so it does not print anything. In Debug build it prints one Foo copy constructor called.

This is an example that NRVO cannot be performed (practically):

#include <iostream>

struct Foo
{
    Foo(int n) : num(n) {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
    int num;
};

Foo bar(bool ok)
{
    Foo a(42);
    Foo b(0);
    if (ok)
        return a;   // No NRVO: a
    return b;       // No NRVO: b
}

int main(int, char**)
{
    bar(true);
    return 0;
}

The two paths would return different local variables, a and b. Since a and b are distinct objects, the compiler cannot collapse both of them to the return value object. It is practically impossible to perform copy elision in all paths. For this example, Visual Studio 2013 cannot perform RVO, and both Release and Debug builds print Foo copy constructor called.

Conclusion

With C++11’s move support, people are talking about the revival of returning value objects. It is true that moving can be much cheaper than copying. However if you are careful and write RVO enabled code, it can beat move, because it is completely free.

As Andrei Alexandrescu said in Going Native 2013, “No work is less work than some work.” To make your code RVO enabled, use either:

  • URVO: all paths return rvalues, or
  • NRVO: all paths return the same local object.
August 5, 2014

C++ Copy Elision

Copying big class objects could be expensive. Moving could be much cheaper. C++ has special rules to allow implementation to omit the copy/move construction of a class object. The purpose to elide the copy/move construction is for better efficiency. This is called copy elision.

There are two class objects in question for copy elision: the source object and the destination object. The source object is used to initialize the destination object. When copy elision is carried out, the source and destination objects collapse into one object, therefore in the code they appear like the aliases of the same single object. This object starts its life when the source object is constructed, and ends when the destination is destructed. With each copy elision, one construction and one matching destruction are omitted for run time saving, and one object is not created for space saving.

Copy elision is optional. The C++ compiler may choose to elide or perform the copy/move construction when copy elision is legally allowed.

The most often seen opportunities of copy elisions are with a function return statement, and copy/move constructing a class object with a temporary object of the same type.

Return Value Copy Elision

C++2011 12.8/31 allows return value copy elision:

– in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

In general, a function’s return value is a distinct object. The rule above says, when the return expression is the name of a local object in the function, whose stripped class type is the same as the return value, then copy elision is allowed. This is possible because this local object is not used otherwise in the function beyond the return statement, so it can be directly constructed as the return value object, i.e., the two objects can be one same thing. This is an example:

#include <iostream>

struct Foo
{
    Foo() {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
};

Foo bar()
{
    Foo a;
    return a;   // copy elision
}

int main(int, char**)
{
    bar();
    return 0;
}

In the bar function, the return statement is copy elision eligible for source local object a and destination return value object. At the main function’s bar call, a return value object is constructed (although it is an unnamed temporary that destructs right away upon the end of bar call code line). When copy elision is in action, the bar function’s local object a is constructed in-line in the main function’s return value object for bar call, and there is no copy constructor call. If the implementation chooses to not use copy elision, then the local object a is a separate object, and at the return statement, Foo’s copy constructor is called to construct the unnamed return value object in the main function for bar call. In my Visual Studio 2013, the Debug build does not perform copy elision and it prints Foo copy constructor called; while the Release build performs copy elision and nothing is printed.

This is an example that is not eligible for copy elision:

#include <iostream>

struct Foo
{
    Foo() {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
};

Foo bar(Foo f)
{
    return f;   // no copy elision
}

int main(int, char**)
{
    bar(Foo());
    return 0;
}

The parameter f of function bar, although considered local in the function, is however not possible to be the elision source of return value. Conceptually the parameter f is constructed by the caller of the bar function before the function is actually called. When the function body starts to run, that parameter object already exists. The return value class object of the bar function, which actually lives in the stack frame of the caller, the main function, has a distinct address than the parameter f. Because they cannot collapse to one address, copy elision is impossible. Since copy elision is not possible, both Debug and Release builds with my Visual Studio 2013 print Foo copy constructor called in this example.

Temporary Object Copy Elision

C++2011 12.8/31 also allows temporary object copy elision:

-- when a temporary class object that has not been bound to a reference would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

This is easy to understand. If you are going to copy/move construct an object from a temporary class object of the same stripped type, you are allowed to construct the temporary in-place in the destination object and avoid the copy/move operation. See this example:

#include <iostream>

struct Foo
{
    Foo() {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
};

int main(int, char**)
{
    Foo a = Foo();  // copy elision
    return 0;
}

In the main function, if there is no copy elision, a temporary Foo object is first default constructed, then the local Foo object a is copy constructed. If copy elision is performed, the temporary object is right constructed in a’s spot, so there is no copy constructor call. Both Debug and Release builds with my Visual Studio 2013 perform copy elision and print nothing in this example.

Chained Copy Elisions

The copy elisions can be combined/chained. For example:

#include <iostream>

struct Foo
{
    Foo() {}
    Foo(const Foo&) { std::cout << "Foo copy constructor called" << std::endl; }
};

Foo bar()
{
    Foo a;
    return a;   // copy elision
}

int main(int, char**)
{
    Foo b = bar();  // copy elision
    return 0;
}

There are two possible copy elisions in the example. The bar function’s return statement can use return value copy elision, as seen in the earlier example. The construction of b in main function can use copy elision from the temporary object, i.e., the return value of bar call. So a valid C++ compiler can choose any of these:

  • Use no copy elision. There are two Foo copy constructor calls. The program would print two lines of Foo copy constructor called.
  • Use one copy elision at either locations. There is one Foo copy constructor call. The program would print one line of Foo copy constructor called. [Visual Studio 2013, Debug build]
  • Use two copy elisions. There is no Foo copy constructor calls. The program would print nothing. [Visual Studio 2013, Release build]

Because C++ is mostly a value based language, rather than reference based languages such as Java and C#, function calls and other expressions may involve temporary objects without your much thinking. Combining and chaining of copy elisions can save significantly for C++ programs.

Conclusion

  • Return value copy elision omits one object construction at return statement.
  • Temporary object copy elision reuses temporary object in constructing a new object.
  • Chaining copy elisions saves even more.

Also:

  • Copy elision is optional. The compiler may or may not perform it. Therefore,
  • If the copy/move constructor has side effects, the side effects are not guaranteed to happen or not happen (as is apparent in the examples above with printing through std::cout). Just do not count on that.

This blog post does not discuss about the copy elisions with throw and catch statements. But essentially, they are similar to return value copy elisions and temporary object copy elisions. You can refer to C++2011 12.8/31 for details.

Today’s compilers are very sophisticated, and most of them would perform copy elision when generating optimized code. An important use of copy elision is Return Value Optimization (RVO), see another post.

Follow

Get every new post delivered to your Inbox.

Join 45 other followers