Sign inorRegister Site is for SALE!
C++
Raiting:
126

More modern C++ type


"C++11 feels like a new language." - Bjarne Stroustrup

Recently, Herb Sutter has opened on its website a new page “Elements of Modern C++ Style”, where he describes the advantages of the new standard and how they will affect the code.

C++11 standard introduces many new features. Next, we focus specifically and only on those features that make C++11 really feel like a new language compared to C++98, namely:

• They change the styles and idioms you will use when writing C++ code, often including the way you will design C++ libraries. For example, you will see more smart pointer parameters and return values, and functions that return big objects by value.
• They will be used so pervasively that you will probably see them in most code examples. For example, virtually every five-line modern C++ code example will say “auto” somewhere.


Feel free to use other features C++11. But get used to these ones first, because these are the pervasive ones that show why C++11 code is clean, safe, and fast – just as clean and safe as code written in any other modern mainstream language, and with C++’s traditional to-the-metal performance as strong as ever.

auto


Use auto wherever possible. It is useful for two reasons. First, most obviously it’s a convenience that lets us avoid repeating a type name that we already stated and the compiler already knows:

// C++98
map<int,string>::iterator i = m.begin();

// C++11
auto i = begin(m);
Second, it’s more than just a convenience when a type has an unknown or unutterable name, such as the type of most lambda functions, that you couldn’t otherwise spell easily or at all.

// C++98
binder2nd< greater<int> > x = bind2nd( greater<int>(), 42 );

// C++11
auto x = [](int i) { return i > 42; };

Note that using auto does not change the code’s meaning. The code is still statically typed, and the type of every expression is already crisp and clear; the language just no longer forces us to redundantly restate the type’s name.

Some people are initially afraid of using auto here, because it may feel like not (re)stating the type we want could mean we’ll get a different type by accident. If you want to explicitly enforce a type conversion, that’s okay; state the target type. The vast majority of the time, however, just use auto; it will rarely be the case that you get a different type by mistake, and even in those cases the language’s strong static typing means the compiler will usually let you know because you’ll be trying to call a member function the variable doesn’t have or otherwise use it as something that it isn’t.

Smart pointers: no need for delete


Always use the standard smart pointers, and non-owning raw pointers. Never use owning raw pointers and delete, (except in rare cases when implementing your own low-level data structure).

In general, a pointer is unique_ptr to express unique ownership, so use it.

// C++98
widget* pw = new widget();
:::
delete pw;

// C++11
auto pw = make_shared<widget>();

Use weak_ptr to break cycles and express optionality (e.g., implementing an object cache).

// C++11
class gadget;

class widget {
private:
shared_ptr<gadget> g;
};

class gadget {
private:
weak_ptr<widget> w;
};

If the pointer should be the sole owner, use unique_ptr, which is designed especially for this case. Any expression of the "new T" should immediately initiate another object that owns it, usually it is unique_ptr.

// C++11 Pimpl Idiom
class widget {
:::
private:
class impl;
unique_ptr<impl> pimpl;
};

// в .cpp файле
class impl {
:::
};

widget::widget()
: pimpl( new impl() )
{
}

If you know another object is going to outlive you and you want to observe it, use a (non-owning) raw pointer.

// C++11
class node {
vector< unique_ptr<node> > children;
node* parent;
public:
:::
};

nullptr


Always use nullptr for a null pointer value, never the literal 0 or the macro NULL which are ambiguous because they could be either an integer or a pointer.

// C++98
int* p = 0;

// C++11
int* p = nullptr;

Range and for


The range-based for loop is a much more convenient way to visit every element of a range in order.

// C++98
for( vector<double>::iterator i = v.begin(); i != v.end(); ++i ) {
total += *i;
}

// C++11
for( auto d : v ) {
total += d;
}

Nonmember begin and end


Always use nonmember begin(x) and end(x) (not x.begin() and x.end()), because begin(x) and end(x) are extensible and can be adapted to work with all container types – even arrays – not just containers that follow the STL style of providing x.begin() and x.end() member functions.

If you’re using a non-STL collection type that provides iteration but not STL-style x.begin() and x.end(), you can often write your own non-member begin(x) and end(x) overloads for that type and then you can traverse collections of that type using the same coding style above as for STL containers. The standard has set the example: C arrays are such a type, and the standard provides begin and end for arrays.

vector<int> v;
int a[100];

// C++98
sort( v.begin(), v.end() );
sort( &a[0], &a[0] + sizeof(a)/sizeof(a[0]) );

// C++11
sort( begin(v), end(v) );
sort( begin(a), end(a) );

Lambda Functions and Algorithms


Lambdas are a game-changer and will frequently change the way you write code to make it more elegant and faster. Lambdas make the existing STL algorithms roughly 100x more usable. Newer C++ libraries increasingly are designed assuming lambdas as available (e.g., PPL), and some even require you to write lambdas to use the library at all (e.g., C++ AMP).

A small example: Find the first element in v that’s >x and <y. In C+11, the simplest and cleanest code is to use a standard algorithm.

// C++98: write a naked loop (using std::find_if is impractically difficult)
vector<int>::iterator i = v.begin(); // because we need to use i later
for( ; i != v.end(); ++i ) {
if( *i > x && *i < y ) break;
}

// C++11: use std::find_if
auto i = find_if( begin(v), end(v), [=](int i) { return i > x && i < y; } );
Get familiar with lambdas. They are already widely available and pervasively used in several popular mainstream languages. A good place to start is Lambdas, Lambdas Everywhere at PDC 2010.

Move / &&


Move semantics change the way we design our APIs. We will be designing for return by value a lot more often.

// C++98: alternatives to avoid copying
vector<int>* make_big_vector(); // option 1: return by pointer: no copy, but don't forget to delete
:::
vector<int>* result = make_big_vector();

void make_big_vector( vector<int>& out ); // option 2: pass out by reference: no copy, but caller needs a named object
:::
vector<int> result;
make_big_vector( result );

// C++11: move
vector<int> make_big_vector(); // usually sufficient for 'callee-allocated out' situations
:::
auto result = make_big_vector(); // guaranteed not to copy the vector
Enable move semantics for a type when you can do something more efficient than copy.

And more


There is more to modern C++, and in the future we will write more in-depth pieces about these and other features of C++11.

But for now, this is the list of must-know features. These features form the core that defines modern C++ style, that make C++ code look and perform the way it does, that you will see used pervasively in nearly every piece of modern code you will see or write… and that make modern C++ the clean, and safe, and fast language that our industry will continue relying on heavily for years to come.
Tags: C++, C++0x, С++11
+2
Skull 13 january 2012, 17:45
Vote for this post
Bring it to the Main Page
 

Comments

Leave a Reply

B
I
U
S
Help
Avaible tags
  • <b>...</b>highlighting important text on the page in bold
  • <i>..</i>highlighting important text on the page in italic
  • <u>...</u>allocated with tag <u> text shownas underlined
  • <s>...</s>allocated with tag <s> text shown as strikethrough
  • <sup>...</sup>, <sub>...</sub>text in the tag <sup> appears as a superscript, <sub> - subscript
  • <blockquote>...</blockquote>For  highlight citation, use the tag <blockquote>
  • <code lang="lang">...</code>highlighting the program code (supported by bash, cpp, cs, css, xml, html, java, javascript, lisp, lua, php, perl, python, ruby, sql, scala, text)
  • <a href="http://...">...</a>link, specify the desired Internet address in the href attribute
  • <img src="http://..." alt="text" />specify the full path of image in the src attribute