constructor, copy constructor, copy assignment

http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three

a post that is very cool and easy to understand

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;public:

    person(const std::string& name,int age): name(name), age(age){}};
int main(){
    person a("Bjarne Stroustrup",60); // constructor
    person b(a);// What happens here? // copy constructor
    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
       ~person(){}

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;
public:
// the constructor acquires a resource:
// in this case, dynamic memory obtained via new[]
    person(constchar* the_name,int the_age){
        name =newchar[strlen(the_name)+1];
        strcpy(name, the_name);
        age = the_age;}
// the destructor must release this resource via delete[]
  ~person() {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 =newchar[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 =newchar[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 =newchar[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:

private:

    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.)

Advice

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.

auto

Given a function with return type as ‘const A&’, if I use ‘auto’ to get the function result as
auto a = func(…);
Will the ‘auto’ be deducted as ‘const A&’ or ‘const A’?

No, it will be just “A” without const or &

#include <iostream>
using namespace std;

const int& func() {return 2;}; //should not do this, because 2 is a local variable…this is just a test of “const”

int main() {
// your code goes here
auto x = func();
x = 1; // x can be assigned with another value
cout << x;
return 0;
}

read more: http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html

pointers and reference

the best sum: http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c

  1. A pointer can be re-assigned:
    int x =5;int y =6;int*p;
    p =&x;
    p =&y;*p =10;
    assert(x ==5);
    assert(y ==10);

    A reference cannot, and must be assigned at initialization:

    int x =5;int y =6;int&r = x;
  2. A pointer has its own memory address and size on the stack (4 bytes on x86), whereas a reference shares the same memory address (with the original variable) but also takes up some space on the stack. Since a reference has the same address as the original variable itself, it is safe to think of a reference as another name for the same variable. Note: What a pointer points to can be on the stack or heap. Ditto a reference. My claim in this statement is not that a pointer must point to the stack. A pointer is just a variable that holds a memory address. This variable is on the stack. Since a reference has its own space on the stack, and since the address is the same as the variable it references. More on stack vs heap. This implies that there is a real address of a reference that the compiler will not tell you.
    int x =0;int&r = x;int*p =&x;int*p2 =&r;
    assert(p == p2);
  3. You can have pointers to pointers to pointers offering extra levels of indirection. Whereas references only offer one level of indirection.
    int x =0;int y =0;int*p =&x;int*q =&y;int**pp =&p;
    pp =&q;//*pp = q**pp =4;
    assert(y ==4);
    assert(x ==0);
  4. Pointer can be assigned NULL directly, whereas reference cannot. If you try hard enough, and you know how, you can make the address of a reference NULL. Likewise, if you try hard enough you can have a reference to a pointer, and then that reference can contain NULL.
    int*p = NULL;int&r = NULL;<--- compiling error
  5. Pointers can iterate over an array, you can use ++ to go to the next item that a pointer is pointing to, and + 4 to go to the 5th element. This is no matter what size the object is that the pointer points to.
  6. A pointer needs to be dereferenced with * to access the memory location it points to, whereas a reference can be used directly. A pointer to a class/struct uses -> to access it’s members whereas a reference uses a ..
  7. A pointer is a variable that holds a memory address. Regardless of how a reference is implemented, a reference has the same memory address as the item it references.
  8. References cannot be stuffed into an array, whereas pointers can be (Mentioned by user @litb)
  9. Const references can be bound to temporaries. Pointers cannot (not without some indirection):
    constint&x =int(12);//legal C++int*y =&int(12);//illegal to dereference a temporary.

    This makes const& safer for use in argument lists and so forth.

 

explicit

From http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean

In C++, the compiler is allowed to make one implicit conversion to resolve the parameters to a function. What this means is that the compiler can use single parameter constructors to convert from one type to another in order to get the right type for a parameter. Here’s an example class with a constructor that can be used for implicit conversions:

classFoo {
public:// single parameter constructor, can be used as an implicit conversion
Foo(int foo): m_foo (foo){}
int GetFoo() {
return m_foo;}
private:int m_foo;
};

Here’s a simple function that takes a Foo object:

void DoBar(Foo foo) {
int i = foo.GetFoo();
}

and here’s where the DoBar function is called.

int main (){
DoBar(42);
}

The parameter is not a Foo object, but an int. However, there exists a constructor for Foo that takes an int so this constructor can be used to convert the parameter to the correct type.

The compiler is allowed to do this once for each parameter.

Prefixing the explicit keyword to the constructor prevents the compiler from using that constructor for implicit conversions. Adding it to the above class will create a compiler error at the function call DoBar (42). It is now necessary to call for conversion explicitly with DoBar (Foo (42))

The reason you might want to do this is to avoid accidental construction that can hide bugs. Contrived example:

  • You have a MyString(int size) class with a constructor that constructs a string of the given size. You have a function print(const MyString&), and you call it with print(3). You expect it to print “3”, but it prints an empty string of length 3 instead.

books

http://it-ebooks.info/

http://stackoverflow.com/questions/tagged/c%2b%2b?sort=votes&pageSize=15

Q: why processing sorted array is faster than un-sorted ones? A: branch prediction

Q: while(x- ->0)  is while( (x–) > 0 )

Q:

int arrary1[3] = { 1, 2, 3 };
int *p = nullptr;
p = arrary1;

printf(“%d\n”, p); // random number, address to int, overflow
printf(“%d\n”, p[0]); // 1
printf(“%d\n”, *(++p)); // 2
printf(“%d\n”, p[0]); // 2

Q: split string

std::vector<std::string> split(const std::string&s,char delim){
std::vector<std::string> elems;
split(s, delim, elems);
return elems;}

Q:

small quiz about r & p

#include <iostream>
#include <stdint.h>
using namespace std;

int main() {
// your code goes here
short int buff[5]  = {1, 1, 1, 1, 0};
cout << *(int32_t*)(&buff[3]); // get the value of the remainder of buff from 3rd position as a int32 value 指 buff第3个位置起,看作一个4位整数
return 0;
}

cout << *(int32_t*)(&buff[3]);  output: 1 from 00000000 00000001 (3rd is 1 and 4th is 0)

cout << *(int32_t*)(&buff[2]); output: 65537 from 00000001 00000001 (2nd is 1 and 3rd is 1 too)

short int has 2 bytes, 16 bits