Moving Is Not Copying -- Andrew Koenig
Moving Is Not Copying
by Andrew Koenig
Like many subtle ideas, the idea of moving data in C++ is built on a simple concept.
October 25, Pavia, Italy
November 6-8, Berlin, Germany
November 3-8, Kona, HI, USA
By Blog Staff | Jun 8, 2013 04:47 PM | Tags: basics
Moving Is Not Copying
by Andrew Koenig
Like many subtle ideas, the idea of moving data in C++ is built on a simple concept.
By Blog Staff | Jun 7, 2013 06:01 PM | Tags: None
Quick A: [x] captures a copy, [&x] remembers a reference to the original variable.
C++ Lambdas: Difference between “mutable” and capture-by-reference
In C++ you can declare lambdas for example like this:
int x = 5; auto a = [=]() mutable { ++x; std::cout << x << '\n'; }; auto b = [&]() { ++x; std::cout << x << '\n'; };Both let me modify
x
, so what is the difference?
By Blog Staff | Jun 7, 2013 05:42 PM | Tags: intermediate basics
The solution to the latest GotW problem is now available:
GotW #92 Solution: Auto Variables, Part 1 (updated for C++11/14)
by Herb Sutter
From the article:
When you’re new to
auto
, the key thing to remember is that you really are declaring your own new local variable. That is, “what’s on the left” is my new variable, and “what’s on the right” is just its initial value:auto my_new_variable = its_initial_value;
You want your new variable to be just like some existing variable or expression over there, and be initialized from it, but that only means that you want the same basic type, not necessarily that other variable’s own personal secondary attributes such as top-level
const
-ness and reference-ness which are per-variable. For example, just because he’sconst
doesn’t mean you’reconst
, and vice versa.It’s kind of like being identical twins: Andy may be genetically just like his brother Bobby and is part of the same family, but he’s not the same person; he’s a distinct person and can make his own choice of clothes and/or jewelry, go to be seen on the scene in different parts of town, and so forth. So your new variable will be just like that other one and be part of the same type family, but it’s not the same variable; it’s a distinct variable with its own choice of whether it wants to be dressed with
const
and/or a reference, may be visible to different threads, and so forth.Remembering this will let us easily answer the rest of our questions...
By Blog Staff | Jun 7, 2013 05:33 AM | Tags: intermediate
A belated link to Andrzej's recent article:
Empty list initialization
by Andrzej Krzemieński
From the article:
My conclusion from the above story is this piece of advice. When you provide an initializer-list constructor for your class, make sure that you also provide a default constructor with the same semantics as though you were initializing with a zero-size
initializer_list
.
By Blog Staff | Jun 5, 2013 05:37 PM | Tags: intermediate
The solution to the latest GotW problem is now available:
GotW #91 Solution: Smart Pointer Parameters (updated for C++11/14)
by Herb Sutter
From the article:
Guideline: Don’t pass a smart pointer as a function parameter unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.
Guideline: Prefer passing objects by value,*
, or&
, not by smart pointer.If you’re saying, “hey, aren’t raw pointers evil?”, that’s excellent, because we’ll address that next...
By Blog Staff | Jun 5, 2013 02:45 PM | Tags: intermediate
Good advice from the designer of the new
std::optional<T>
on how to design modern C++ classes to follow GotW #1's advice to avoid writing initializer_list
constructors that force callers to resort to ()
instead of {}
to disambiguate.
Intuitive Interface -- Part I
by Andrzej Krzemieński
From the article:
Let’s start with the popular C++(11) “uniform initialization” gotcha. Changing braces to parentheses in object initialization may change the semantics of the initialization:
std::vector<int> v1{5, 6}; // 2 elems: {5, 6} std::vector<int> v2(5, 6); // 5 elems: {6, 6, 6, 6, 6}For instance, it is described in Problem 1 of the newly revisited “Guru of The Week” series by Herb Sutter.
When seeing such an example, one might conclude that the new rules for object initialization are very confusing or error-prone. But to me it looks like the problem here lies in how class template
std::vector
has been defined in C++03...
By Blog Staff | Jun 5, 2013 08:05 AM | Tags: None
Quick A: Yes, but some compilers have conforming extensions that give meaning to nonportable programs.
Preventing narrowing conversion when using std::initializer_list
#include <iostream> struct X { X(std::initializer_list<int> list) { std::cout << "list" << std::endl; } X(float f) { std::cout << "float" << std::endl; } }; int main() { int x { 1.0f }; X a(1); // float (implicit conversion) X b{1}; // list X c(1.0f); // float X d{1.0f}; // list (narrowing conversion) ARG!!! // warning: narrowing conversion of '1.0e+0f' from 'float' to 'int' // inside { } [-Wnarrowing] }Is there any other way of removing
std::initializer_list
from an overload list (i.e., making the non-list ctors more favorable) instead of using the()
-initialization, or at least prohibiting narrowing conversion to happen (apart from turning warning into error)?I was using http://coliru.stacked-crooked.com/ compiler which uses GCC 4.8.
By Blog Staff | Jun 4, 2013 04:46 PM | Tags: intermediate
On Friday, June 14, Scott Meyers will be giving a talk open to the public at the Oslo C++ Users Group.
From Scott's announcement:
Lambdas vs. std::bind in C++11 and C++14
Scott Meyers
C++ developers have long had a need to bind functions and arguments together for a later call. This is what makes it possible to invoke member functions on objects inside STL algorithms. The same technology can be used to create custom callback functions and to adapt function interfaces to different calling contexts.
In C++98, such binding was accomplished via
std::bind1st
andstd::bind2nd
. TR1 addedstd::tr1::bind
, which was promoted tostd::bind
in C++11. But C++11 also introduced lambda expressions, and they’re slated to become even more powerful in C++14. That means that there are now two mechanisms in C++ for binding functions to arguments for later calls:std::bind
and lambda expressions. In this talk, Scott examines the pros and cons of each approach, comparing them in terms of expressiveness, clarity, and efficiency, and he comes to the conclusion that one should almost always be used instead of the other. But which one?
This presentation assumes a basic familiarity with
std::bind
and C++11 lambda expressions.
By Blog Staff | Jun 4, 2013 11:08 AM | Tags: None
Introduction to the C++11 feature: trailing return types
by sumi_cj
From the article:
To solve this problem, C++11 introduced a feature called trailing return types. Using this feature, the previous program can be rewritten as follows:
template<class T> auto mul(T a, T b) -> decltype(a*b){ return a*b; }
By Blog Staff | Jun 3, 2013 03:37 PM | Tags: basics
Quick A: In C++11, prefer to initialize using {}
where possible, which is nearly always.
Uniform initialization syntax difference
What's the difference between doing
A a{ A() };and,
A a( A{} );to avoid the Most Vexing Parse? When should I use a particular one?