Container changes in C++11
The recently approved C++11 standard brings a lot of welcome changes to C++ that modernize the language a little bit. Among the many changes, we find that containers have received some special love.
Initialization
C++ was long behind modern languages when it came to initializing containers. While you could do
int a[] = {1, 2, 3};
for simple arrays, things tended to get more verbose for more complex containers:
vector<string> v;
v.push_back("One");
v.push_back("Two");
v.push_back("Three");
C++11 has introduced an easier, simpler way to initialize this:
vector<string> v = {"One", "Two", "Three"};
The effects of the changes are even better for things like maps, which could get cumbersome quickly:
map<string, vector<string> > m;
vector<string> v1;
v1.push_back("A");
v1.push_back("B");
v1.push_back("C");
vector<string> v2;
v2.push_back("A");
v2.push_back("B");
v2.push_back("C");
m["One"] = v1;
m["Two"] = v2;
This can now be expressed as:
map<string, vector<string>> m = {{"One", {"A", "B", "C"}},
{"Two", {"Z", "Y", "X"}}};
Much simpler and in line with most modern languages. As an aside, there’s another change in C++11 that would be easy to miss in the code above. The declaration
map<string, vector<string>> m;
was illegal until now due to >> always being evaluated to the right-shift operator; a space would always be required, like
map<string, vector<string> > m
No longer the case.
Iterating
Iterating through containers was also inconvenient. Iterating the simple vector v above:
for (vector<string>::iterator i = v.begin();
i != v.end(); i++)
cout << i << endl;
Modern languages have long had some foreach equivalent that allowed us easier ways to iterate through these structures without having to explicitly worry about iterators types. C++11 is finally catching up:
for (string s : v)
cout << s << endl;
As well, C++11 brings in a new keyword, auto, that will evaluate to a type in compile-type. So instead of
for (map<string, vector<string> >::iterator i = m.begin();
i != m.end(); i++) {
we can now write
for (auto i = m.begin(); i != m.end(); i++) {
and auto will evaluate to map<string, vector<string>>::iterator.
Combining these changes, we move from the horrendous
for (map<string, vector<string> >::iterator i = m.begin();
i != m.end(); i++)
for (vector<string>::iterator j = i->second.begin();
j != i->second.end(); j++)
cout << i->first << ': ' << *j << endl;
to the much simpler
for (auto i : m)
for (auto j : i.second)
cout << i.first << ': ' << j << endl;
Not bad.
C++11 support varies a lot from compiler to compiler, but all of the changes above are already supported in the latest versions of GCC, LLVM, and MSVC compilers.
Syndicated 2012-12-15 14:41:36 from robteix dot com