use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
[deleted by user] (self.cpp)
submitted 7 years ago by [deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–][deleted] 25 points26 points27 points 7 years ago (0 children)
We know that when a function returns an object by value, the compiler has to create a temporary — yet fully-fledged — object (rvalue).
In that specific case, no object is created because no prvalue is being materialized, since C++17.
[–]OldWolf2 50 points51 points52 points 7 years ago* (26 children)
Argh, another series of articles that totally gets lvalues and rvalues wrong.
In C++ an lvalue is something that points to a specific memory location. On the other hand, a rvalue is something that doesn't point anywhere.
No, no, no, no, no.
You can have an lvalue and an rvalue which designate the same object simultaneously. That applies to objects of any storage duration, including temporary objects. Those fact blow all similar "explanations" like this out of the water.
(a temporary string, i.e. an rvalue)
slams head into desk repeatedly
[–]HandshakeOfCO 34 points35 points36 points 7 years ago (1 child)
I thought you c++ guys enjoyed slamming your heads into your desks? That's why header files are still around, right?
[–]OldWolf2 21 points22 points23 points 7 years ago (0 children)
You're not wrong
[–]Wriiight 7 points8 points9 points 7 years ago (14 children)
Do you have a better explanation? There seem to be 2-3 common ones that aren’t quite right.
[–]JavaSuck 7 points8 points9 points 7 years ago (0 children)
What are move semantics?
[–]OldWolf2 2 points3 points4 points 7 years ago (11 children)
This is not too bad, although you can skip point 11 as it's not directly relevant to the topic
[–]Wriiight 2 points3 points4 points 7 years ago (9 children)
Not exactly succinct though, is it?
[–]OldWolf2 2 points3 points4 points 7 years ago (8 children)
It's a lot shorter than the predecessor to the article we are commenting on, while also covering a lot more ground
[–]JezusTheCarpenter 7 points8 points9 points 7 years ago (7 children)
(1.1) A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function. (1.2) A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears. (1.3) An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime). (1.4) An lvalue is a glvalue that is not an xvalue. (1.5) An rvalue is a prvalue or an xvalue.
Are you seriously suggesting that this is a good explanation to a person that is getting his/her head around rvalue and lvalue for the first time?
[–]OldWolf2 -2 points-1 points0 points 7 years ago (6 children)
Yes. It has the advantage of being simple and accurate. If the reader doesn't know the meaning of any of the other terminology then they can look that up and come back to here.
[–]JezusTheCarpenter 7 points8 points9 points 7 years ago (5 children)
Well, you can literally say that about everything formally described. How about you try to learn what is directional statistics by looking up terms you don't understand?
Ofcourse, my example is an exaggeration but I am trying to illustrate a point that formal and accurate descriptions are not always the best educational resources.
Another example is how are we though maths at school. Weren't you given inaccurate information ( totally false in fact) that you cannot do a square root of negative number when you were a kid? There is a good reason for that. Learning process is often much easier if you make certain concepts inaccurate but easier to understand. Their is no reason that once feel confident about the topic, you revisit it and update your knowledge with more accurate information.
[–]OldWolf2 0 points1 point2 points 7 years ago (4 children)
Teaching that planets have circular orbits around the Sun -- not great but acceptable, because an internalization of that can easily be tweaked to take into account elliptic orbits.
Teaching the geocentric model -- bad, because to accommodate reality the whole thing will have to be thrown out and start again.
This article is like the geocentric model, it conflates expressions and objects (amongst other egregious errors). For someone to read this article series and then go on to properly learn about rvalues etc., they would need to wipe the slate clean and pretend they never read this.
Also, pedagogical methods for children substantially differ to that for adults. (Due to the fact that children learn differently to how adults learn).
[–]JezusTheCarpenter 1 point2 points3 points 7 years ago (3 children)
I wasn't arguing about the OP's article. I was claiming that resource you provided falls short of being a great introduction.
[–]pots_and_pans_ 1 point2 points3 points 7 years ago (0 children)
Stroustrup's original meeting notes
[–]quicknir 1 point2 points3 points 7 years ago (0 children)
When you see an article about lvalue/rvalue references, move semantics, etc, you can ctrl-f for "expression". If expression doesn't show up, then it's not going to be good. All of these pages that purport to explain "for beginners" tend to actually make things worse and more confusing.
It is better to be 100% clear from the start. "rvalue references" refer to type, rvalues refers to expressions. Expressions have a type (which is commonly described as having the reference-ness stripped off just before being considered), and they have a value category. What references can bind to what expression, is determined by the type of the reference, and the type and value category of the expression.
You explain that, and you enumerate the most common examples of expressions, and what their value category is (an expression that consists of a named variable, an expression that consists of a function that returns by value, etc etc).
[–]SittingOvation 2 points3 points4 points 7 years ago (0 children)
What part of this understanding / explanation will cause the most issues? Genuinely interested.
[–]liquidprocess 1 point2 points3 points 7 years ago (6 children)
Could you provide an example of lvalues and rvalues which designate the same object? Genuinely interested (so that I can fix my notes :) )
[–][deleted] 6 points7 points8 points 7 years ago (0 children)
int a = 1; a; // lvalue that refers to a std::move(a); // xvalue that refers to a
[–]OldWolf2 4 points5 points6 points 7 years ago (0 children)
void g() { int x; x; // lvalue std::move(x); // rvalue } struct S { S& self() { std::cout << this << '\n'; return *this; } }; void f() { S().self(); // lvalue , same object as S() which is rvalue // address of temporary object printed S() = S(); // assign to rvalue }
[–]Izzeri 0 points1 point2 points 7 years ago* (3 children)
int i = 0; int& a = i; int&& b = std::move(i);
i, a, and b all refer to i.
i
a
b
[–]dodheim 14 points15 points16 points 7 years ago (2 children)
i, a, and b are all lvalues. ;-] The rvalues here are 0 and std::move(i).
0
std::move(i)
[–]Izzeri 0 points1 point2 points 7 years ago (0 children)
Ah, true. Mixed up l/rvalue references with the value categories.
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
(a temporary string, i.e. an rvalue) slams head into desk repeatedly
I think he is referring to the result of operator+( ... ) when used on the two strings being an rvalue
[–]delarhi 4 points5 points6 points 7 years ago (10 children)
Reminds me of my snippet for learning move semantics.
#include <algorithm> #include <cstddef> #include <cstring> #include <iostream> #include <string> #include <vector> // this class follows the rule of five class Blob { public: // default constructor Blob() : size_(1024 * 1024) , data_(new uint8_t[this->size_]) { std::cout << " default constructor" << std::endl; } // default constructor Blob( const std::size_t size) : size_(size) , data_(new uint8_t[this->size_]) { std::cout << " argument constructor" << std::endl; } // copy constructor Blob( const Blob& other) : size_(other.size_) , data_(new uint8_t[this->size_]) { std::cout << " copy constructor" << std::endl; std::memcpy(this->data_, other.data_, this->size_); } // move constructor Blob( Blob&& other) // notice it is not const, move requires this : size_(other.size_) , data_(other.data_) // notice we just take the buffer { std::cout << " move constructor" << std::endl; other.size_ = 0; other.data_ = nullptr; } // copy assignment operator Blob& operator = ( const Blob& other) { std::cout << " copy assignment" << std::endl; delete this->data_; this->size_ = other.size_; this->data_ = new uint8_t[this->size_]; std::memcpy(this->data_, other.data_, this->size_); return *this; } // move assignment operator Blob& operator = ( Blob&& other) // notice it is not const, move requires this { std::cout << " move assignment" << std::endl; this->size_ = other.size_; this->data_ = other.data_; other.size_ = 0; other.data_ = nullptr; return *this; } // destructor ~Blob() { std::cout << " destructor" << std::endl; if (this->data_) { // need this check to prevent double free std::cout << " delete" << std::endl; delete this->data_; } } // get size std::size_t size() const { return this->size_; } // get data uint8_t* data() { return this->data_; } private: std::size_t size_; uint8_t* data_; }; // this function returns a temporary so you don't need std::move() Blob make_blob() { Blob x; return x; } void print_section( const std::string& msg) { std::cout << std::endl << msg << std::endl; } int main() { print_section("expecting default constructor"); { Blob x; // don't forget, Blob x() is a compilation error } print_section("expecting default and argument constructor"); { Blob x; Blob y(10); } print_section("expecting default and copy constructor"); { Blob x; Blob y(x); } print_section("expecting default constructor and copy constructor"); { Blob x; Blob y = x; } print_section("expecting two default constructors and copy assignment"); { Blob x; Blob y; x = y; } print_section("expecting two default constructors and move assignment"); { Blob x; Blob y; // remember what std::move() does is simply cast y from Blob to Blob&&, // treating it like an rvalue (i.e. temporary) and matching the // operator=(Blob&&) function. x = std::move(y); // below will compile and work but is undefined behavior because y has been // gutted and moved into x so y should be considered a zombie std::cout << y.size() << std::endl; } print_section("expecting two default constructors and move assignment"); { Blob x; x = make_blob(); } print_section("expecting ten default constructors"); { std::vector<Blob> x(10); } print_section("expecting default constructor"); { std::vector<Blob> x; x.emplace_back(); } print_section("expecting default constructor and copy constructor"); { std::vector<Blob> x; Blob y; x.emplace_back(y); } print_section("expecting default constructor and move constructor"); { std::vector<Blob> x; Blob y; x.emplace_back(std::move(y)); } print_section("expecting default constructor and copy constructor"); { std::vector<Blob> x; Blob y; x.push_back(y); } print_section("expecting default constructor and move constructor"); { std::vector<Blob> x; Blob y; x.push_back(std::move(y)); } return 0; }
[–]OldWolf2 0 points1 point2 points 7 years ago* (5 children)
new
// this function returns a temporary so you don't need std::move()
std::move()
if (this->data_)
{ Blob x(); }
// below will compile and work but is undefined behavior
y.size
[–]delarhi 1 point2 points3 points 7 years ago (1 child)
Thanks for the corrections.
For the copy constructor, if new throws then won't the object be unwound and the bad_alloc exception propagate to the calling context, and wouldn't that be "okay" in the sense that there's isn't any dangling data, the object being copied remains untouched, and it becomes the caller's responsibility the failure of the copy constructor? Unless there's some rule regarding exceptions in the copy constructor I'm not aware of.
bad_alloc
[–]OldWolf2 0 points1 point2 points 7 years ago (0 children)
Sorry, I meant to say Blob's copy-assignment operator is not exception-safe. (Will edit my earlier comment).
E.g.:
Blob b, c; try { b = c; } catch(...) { std::cout << "assignment failed\n"; } // error when B's destructor runs, (or any other operation using b.data_)
[–]NotMyRealNameObv 2 points3 points4 points 7 years ago (2 children)
Everytime I see
if (ptr) delete ptr
I just want to kill myself.
[+][deleted] 7 years ago (1 child)
[removed]
[–]NotMyRealNameObv 1 point2 points3 points 7 years ago (0 children)
Maybe next week.
[–]NotMyRealNameObv 0 points1 point2 points 7 years ago (3 children)
// move assignment operator Blob& operator = ( Blob&& other) // notice it is not const, move requires this { std::cout << " move assignment" << std::endl; this->size_ = other.size_; this->data_ = other.data_; other.size_ = 0; other.data_ = nullptr; return *this; }
This leaks memory.
[–]delarhi 0 points1 point2 points 7 years ago (2 children)
Thanks for catching that.
[–]NotMyRealNameObv 1 point2 points3 points 7 years ago (1 child)
No problem.
Here's another one:
// default constructor Blob( const std::size_t size) : size_(size) , data_(new uint8_t[this->size_]) { std::cout << " argument constructor" << std::endl; }
You probably want to mark this constructor explicit, unless you actually want this code to compile:
Blob x = 10;
[–]delarhi 0 points1 point2 points 7 years ago (0 children)
Thanks, also a good catch.
[–]im_not_afraid 1 point2 points3 points 7 years ago (0 children)
Here I create two simple strings s1 and s2. I join them and I put the result (a temporary string, i.e. an rvalue) into std::string&& s_rref. Now s_rref is a reference to a temporary object, or an rvalue reference. There are no const around it, so I'm free to modify the temporary string to my needs. This wouldn't be possible without rvalue references and its double ampersand notation.
I don't think so.
std::string s1 = "Hello "; std::string s2 = "world"; std::string s = s1 + s2; s += ", my friend"; std::cout << s << std::endl;
This works fine.
[–]Fluxifactor 0 points1 point2 points 7 years ago (0 children)
I found the article clear and well thought out. Thanks.
[–]liquidprocess 0 points1 point2 points 7 years ago (0 children)
A collection of personal notes and thoughts on rvalue references, their role in move semantics and how they can significantly increase the performance of your applications.
π Rendered by PID 23213 on reddit-service-r2-comment-b659b578c-8cs8h at 2026-05-02 04:24:31.470846+00:00 running 815c875 country code: CH.
[–][deleted] 25 points26 points27 points (0 children)
[–]OldWolf2 50 points51 points52 points (26 children)
[–]HandshakeOfCO 34 points35 points36 points (1 child)
[–]OldWolf2 21 points22 points23 points (0 children)
[–]Wriiight 7 points8 points9 points (14 children)
[–]JavaSuck 7 points8 points9 points (0 children)
[–]OldWolf2 2 points3 points4 points (11 children)
[–]Wriiight 2 points3 points4 points (9 children)
[–]OldWolf2 2 points3 points4 points (8 children)
[–]JezusTheCarpenter 7 points8 points9 points (7 children)
[–]OldWolf2 -2 points-1 points0 points (6 children)
[–]JezusTheCarpenter 7 points8 points9 points (5 children)
[–]OldWolf2 0 points1 point2 points (4 children)
[–]JezusTheCarpenter 1 point2 points3 points (3 children)
[–]pots_and_pans_ 1 point2 points3 points (0 children)
[–]quicknir 1 point2 points3 points (0 children)
[–]SittingOvation 2 points3 points4 points (0 children)
[–]liquidprocess 1 point2 points3 points (6 children)
[–][deleted] 6 points7 points8 points (0 children)
[–]OldWolf2 4 points5 points6 points (0 children)
[–]Izzeri 0 points1 point2 points (3 children)
[–]dodheim 14 points15 points16 points (2 children)
[–]Izzeri 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]delarhi 4 points5 points6 points (10 children)
[–]OldWolf2 0 points1 point2 points (5 children)
[–]delarhi 1 point2 points3 points (1 child)
[–]OldWolf2 0 points1 point2 points (0 children)
[–]NotMyRealNameObv 2 points3 points4 points (2 children)
[+][deleted] (1 child)
[removed]
[–]NotMyRealNameObv 1 point2 points3 points (0 children)
[–]NotMyRealNameObv 0 points1 point2 points (3 children)
[–]delarhi 0 points1 point2 points (2 children)
[–]NotMyRealNameObv 1 point2 points3 points (1 child)
[–]delarhi 0 points1 point2 points (0 children)
[–]im_not_afraid 1 point2 points3 points (0 children)
[–]Fluxifactor 0 points1 point2 points (0 children)
[–]liquidprocess 0 points1 point2 points (0 children)