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.
November 14-16, Berlin, Germany
November 18-23, Wrocław, Poland
November 25, Wrocław, Poland
February 10-15, Hagenberg, Austria
March 19-21, Madrid, Spain
April 1-4, Bristol, UK
June 16-21, Sofia, Bulgaria
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 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?
By Blog Staff | Jun 3, 2013 12:47 PM | Tags: intermediate
Quick A: No.
Some authors wrote "Consider doing this" in C++98. The answer is now a definite "No" because it prevents move from returned values.
Isn't the const modifier here unnecessary?
The "Effective C++" Item 3 says "Use
const
whenever possible", and it gives an example like:
const Rational operator*(const Rational& lhs, const Rational& rhs);to prevent clients from being able to commit atrocities like this:
Rational a, b, c; ... (a * b) = c; // invoke operator= on the result of a*b!But isn't the non-reference return value of functions allready a rvalue? So why bother doing this?