New c++11 standard

New type

c++11 adds

  • long long
  • unsingned long long
  • char16_t
  • char32_t

Uniform initialization

c++11 extends the applicability of the brace-enclosed list (list initialization)

int x = {5};
double y {2.7};
short quar[2] = {1,2}
int * ar = new int [2] {1,2};

class Test {
private:
    int aa;
    int bb;
public:
    Test(int a, int b): aa(a), bb(b) {}
}

Test t1(1,2);
Test t2{1,2};
test t3 = {1,2};

std::initializer_list

Can be used as a constructor argument.

vector<int> a1(10); // uninitialized vector with 10 elements
vector<int> a2{10}; // initializer-ist a2 has 1 elements set to 10
vecotr<int> a3{1,2,3}; // 3 elements set to 1,2,3

You can use an initializer_list argument for regular function as well as for constructor

#include <initializer_list>
double sum(std::initializer_list<double> li);
int main() 
{
    double total = sum({1,2,3})
}

double sum(std::initializer_list<double> ii)
{
    double tot = 0;
    for (auto p = il.begin(); p != il.end(); p++)
        tot += *p;
    return tot;
}

Declarations

auto

c++11 strips the keyword auto of its former meaning as a storage class specifier and puts it to use to implement automatic type deduction, provided that an explicit initializer is given.

auto a = 1; // a is type int
auto pta = &a; // pta is type int *
double b(double, int);
...
for(auto p = il.begin(); p != il.end(); p++);

decltype

Create a variable of the type indicated by an expression.

// decltype(x) y;
double x;
int n;
decltype(x*n) q; // q same type as x*n, double
decltype(&x) pd; // pd same as &x, double *
//useful in template defininitions
template<typename T, typename U>
void ef(T t, U u)
{
    decltype(T*U) tu;
}

Trailing Return type

To use combination with decltype

double f1(double int);
auto f2(double, int) -> double;

template<typename T, typename U>
auto ef(T t, U u): decltype(T*U)
{
    decltype(T*U) tu;
}

Template Aliases: using =

typedef double newDouble;
using newDouble = double;
template<typename T> using newDoubleArr = std::arrary<T, 12>

nullptr

The null pointer is a pointer guaranteed not to point to valid data. It's same as pt = 0;

Smart Pointers

  • unique_ptr
  • shared_ptr
  • weak_ptr

Scoped Enumerations

You can use New1::yes and New2::yes.

enum Old {yes, no};
enum class New1 {yes, no};
enum struct New2 {yes, no};

Class Changes

explicit Conversion Operators

Introduce the keyword explicit to suppress automatic conversions invoked by one-argument constructor:

class Test
{
    Test(int);
    explicit Test(double);
}

Test a, b;
a = 5; // implicit converstion, call Test(int)
b = 0.5 // not allowed
b = Test(0.5) // explicit conversion

conversion functions can be treated similarly:

class Test
{
    operator int() const;
    explicit operator double() const;
}
...
Test a, b;
int n = a; // int-to-Test automatic conversion;
double x= b // not allowrd
x = double(b) // explicit convesrion, allowd

Member In-Class Initialization

class Test
{
    int aval = 1;
    int bval = 2;
    int cval = 3;
public:
    Test() {}
    Test(int c): cval(c) {}
    Test(int a, int b, int c): aval(a), bval(b), cval(c) {}
}

Template and STL Changes

Range-based for Loop

Use range-based for loop, such as the STL containers, that have begin() and end() methods identifying range.

double prices[3] =  {1, 2, 3}
for (auto x: prices)
  cout << x << endl;
// Modify elements
for (auto & x: prices)
  x = x + 1;

New STL Containtes

  • forward_list: single linked list.
  • unorderd_map, set, multimap, multset.
  • arrary: Can't change the size but it have the begin() and end.
std::arrary<int, 3> ar;

New STL Methods

AngleBrackets

std::vector<std::list<int> > // >> not ok befor c++11
std::vector<std::list<int>> // ok in c++11

The rvalue reference

lvalue

is an expression, such as a variable name or dereferenced pointer, that represents data for which the program can obtain an address. Originally lvalue was one that could appear on the left side of assignment expression, but the advent of the const modifier allowed for constructs that cannot be assigned but which still addressable;

lvalue reference

is an identifier that can binds an lvalue.

int n;              // lvalue
int * pt = new int; // lvalue
const int b = 101;  // lvalue
int & rn = n;       // lvalue reference
int & rt = *pt;     // lvalue reference
cont int & rb = b;  // lvalue reference

rvalue

is an values that can appear on the left side of assignment expression but for which cannot apply the address operator. literal constants, expression such as x+y and function return values, providing the function dose not a reference

rvalue reference

is identifier that can binds an rvalue;

int x = 10                     // rvalue
int y = 20                     // rvalue
int && r1 = 13;                // rvalue reference
int && r2 = x + y;             // rvalue reference. bind the value to which x + y evaluates at that time.
double && r3 = std::sqrt(2.0); // revalue reference

Reference declaration

Declares a named variable a s a reference, that is, an alias to already-existing object or function. - & (attr) declarator: Lvalue reference declarator: the declaration S& D; declares D as an lvalue reference to the type determined by decl-specifier-seq S - && (attr) declarator: Rvalue reference declarator: the declaration S&& D: declares D as an rvalue reference to the type determined by decl-specifier-seq S.

Move Semantics and the Rvalue Reference

The Need for Move Semantics

Let the compiler know the it needs to do a real copy and when it doesn't. Compiler modifies code to remove redundant job.

Move Semantic

vector<string> upper(vecter<string>& vs) 
{
    vector<string> temp;
    //code the store all upper case to temp
    return temp;

}
vector<string> vstr(100);
vector<string> vstr_copy1(vstr);        // #1
vector<string> vstr_copy2(upper(vstr)); // #2
#1

To make copy of vstr, vstr copy constructor will called.

#2
  1. create temp object which is upper case version of vstr.
  2. vstr_copy2 call copy constructor of temp object.
  3. delete temp object. Step 2 is redundant in this case. It's better the compiler transfer ownership of the data to vstr_copy2.
Example

When you move a file from one directory to another: The actual file stays where is is on the hard drive, and just the booking is altered. Somewhat paradoxically move semantic avoids moving the primary data;it just adjusts booking To implement move semantic, we need a way to let the compiler know the it needs to do a real copy and when it doesn't. Here's where the rvalue reference comes into play. We can define two constructor. One the regular copy constructor. The other, called move constructor, can use an rvalue reference, and it can bind to rvalue arguments, such as return value of upper(vsrt).. The copy constructor do the usually deep copy, while the move constructor can just adjust booking. A move constructor may alter its argument, and this implies that an rvalue reference parameter should not be const.

Useless::Useless(Useless&& u): num(u.num) //move constructor
{
    ++ct;
    pt = u.pt; // steal address
    u.pt = nullptr; // give old object nothing in return
    u.num = 0;
    showObj();
    cout << "move construtor(Useless&& u)" << endl;
}
  • Move constructor make new object based on rvalue reference.
  • Must pilfering original memory assigned by new, because it'll be called twice if it is not done. code

Move Constructor Observation

Useless two = one // matches Useless::Useless(const Useless &) = copy constructor
Useless four (one + three) // matched Useless::Useless(const Useless &&) = move constructor

Before Move constructor

Useless four (one + three) // matched Useless::Useless(const Useless &&) = move constructor
  1. Operator+() makes temp1 object.
  2. Expression (temp1) calls copy constructor. According to spec, create new temp2 object, because it is a rvalue not a lvalue.
  3. Copy temp2 to crate four.
  4. delete temp1, temp2

Assignment

Useless & Uesless::operator+(const Useless & f)
{
    if (this == f)
        return *this;
    delete[] pc;
    n = f.n;
    pc = new char[n];
    for (int i = 0; i < n; i++)
        pc[i] = f.pc[i]
    return *this;
}

Useless & Useless::operation=(Useless && f)  //not a const! because method alter the source object.
{
    if (this == f)
        return *this;
    delete[] pc;
    n = f.n;
    pc = f.pc; // pilfers the source object
    f.n = 0;
    f.pc = nullptr; // only one pointer to point to the data
    return *this;
}

Forcing a Move

  • You can use std::move() function, If you want to use move constructor and move assignment with lvalue
  • std::move is same as using the staitc_cast<> operator to case the object to type Type &&.

From

C++ Primer Plus (6th Edition)