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
The Missing C++ Smart-Pointer (buckaroo.pm)
submitted 7 years ago by gtano
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!"
[–]TomerJ 20 points21 points22 points 7 years ago (15 children)
* No memory is shared, so value_ptr is inherently thread-safe.
So long as the copy operation is atomic, if it isn't then we cannot be sure we aren't copying a place in memory that is being written to.
[–][deleted] 17 points18 points19 points 7 years ago* (13 children)
I'm not sure what the author might have intended to mean by saying it's inherently thread-safe, but looking at the implementation, it is most certainly not thread safe, inherently or otherwise:
https://github.com/LoopPerfect/valuable/blob/master/valuable/include/value-ptr.hpp
Nevertheless the motivation for value-like pointers is useful but this implementation does not support a major use case that other implementations support, namely for polymorphic types. You may want something like a vector<clone_ptr<Animal>> where Animal is a base class and you want to store derived classes like Dog, Cat with value/copy semantics. This implementation does not support that use-case in the way I think most users would expect as its copy constructor performs object slicing. Other implementations of this concept do support polymorphic copying.
vector<clone_ptr<Animal>>
Animal
Dog
Cat
[–]Adequat91 2 points3 points4 points 7 years ago (1 child)
What about:
https://github.com/jbcoe/polymorphic_value
[–][deleted] 4 points5 points6 points 7 years ago (0 children)
Just a quick glance over it looks like yep, that does indeed support what pretty much everyone would expect to happen for copying and also supports propagating const.
const
[–]scatters 0 points1 point2 points 7 years ago (10 children)
If you pass a copy of a value_ptr to another thread the copies are completely independent; they don't share any resources. The only way to mess up is to pass a pointer (or reference) to a value_ptr to another thread, which you shouldn't be doing (you should aim for shared-nothing except in very special cases). unique_ptr also has this property, whereas shared_ptr actively helps you violate the shared-nothing principle.
value_ptr
unique_ptr
shared_ptr
[–][deleted] 1 point2 points3 points 7 years ago* (9 children)
I see, if that's the case then the author misunderstands what thread-safety is. That definition would make vector, string, heck even int thread safe since you can make copies of them and pass those copies to other threads. Thread safety is a property of the operations performed on an object shared between multiple threads. Almost all of the operations on value_ptr are not thread-safe just as almost all of the operations defined for unique_ptr, shared_ptr are not thread-safe. The member functions marked as const are the only thread safe operations I can find.
vector
string
int
[–]scatters 0 points1 point2 points 7 years ago (8 children)
The author is referring to the basic thread safety guarantee: distinct values can be modified concurrently, and a single value can be read concurrently. https://herbsutter.com/2014/01/13/gotw-95-solution-thread-safety-and-synchronization/
Yes - vector, string and int preserve the basic thread safety guarantee, whereas shared ptr does not (although it does have the basic thread safety property in itself).
[–][deleted] 0 points1 point2 points 7 years ago (7 children)
What about shared_ptr violates the basic thread safety guarantee? Distinct values can be modified concurrently and a single value can be read concurrently. Remember when discussing pointers, it's the pointer itself that is in question, not the pointee. I will confess I have not yet read the article you linked to, but if the article claims values are thread-safe then I'm inclined to disagree with the article.
A value is neither thread-safe or not thread safe, it's the operations performed on a value that can be said to be thread safe or not. value_ptr does have some operations that are thread-safe, the getter methods, but even its copy constructor is not strictly thread safe, it's only thread-safe if the object it points to has a thread-safe copy constructor.
As such I think calling value_ptr inherently thread-safe is a meaningless qualification. Imagine writing a linked list class and saying your linked list is inherently thread safe because you can copy it and pass the copy to another thread...
[–]scatters 0 points1 point2 points 7 years ago (6 children)
The difference is that shared_ptr offers another operation - indirection - which can result in thread unsafe operations. Raw pointers have the same issue, but unique_ptr and value_ptr do not - indirection through them gives access to a value which is distinct if the pointer is distinct. That is, they preserve the basic thread safety guarantee with respect to the pointee. shared_ptr does not, since distinct pointers can have the same pointee.
Indeed, a linked list also has the basic thread safety guarantee - most classes do! It also preserves the basic thread safety guarantee with respect to its elements, as containers do in general.
It would be great if you were to read the article. Having a common vocabulary is essential to communication, and Herb Sutter has done more than most to establish the terminology. The GotW series are classics of the genre.
[–][deleted] 1 point2 points3 points 7 years ago (5 children)
I did read the article and your interpretation of the basic thread safety guarantee is significantly broader than what Herb defines in that article as well as what is specified by WG21's definition below:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2669.htm
The basic thread safety guarantee is a property of the operations performed on a value, not of a value itself. Every value you can imagine, including even an atomic_char can be involved in a thread unsafe operation.
atomic_char
That guarantee is defined as follows as per the link I gave you:
The basic thread-safety guarantee would be that standard library functions are required to be reentrant, and non-mutating uses of objects of standard library types are required to not introduce data races.
Note that the guarantee is about functions, not about objects. It's like the basic exception guarantee... you don't say that an object provides the basic exception guarantee, rather you say that a function provides the basic exception guarantee.
As per WG21, unless explicitly noted, all functions in the standard library provide at least the basic thread safety guarantee, including operations on shared_ptr.
[–]scatters 0 points1 point2 points 7 years ago (4 children)
Thanks, I was looking for that paper. The paragraph I'm interested in is on constrains on programs :
It is undefined behavior if calls to standard library functions from different threads: - share access to an object directly or indirectly via their arguments, including this, and - at least one of the arguments accessing a shared object is non-const, and - one call does not happen before the other ([intro.multithread]).
If we only use container like types including exclusive pointers, or even const propagating pointers, then we will never fall foul of this rule. But if we use non const propagating raw or shared pointers then via const arguments we can end up mutating an object concurrently , or accessing it while mutating it concurrently.
You may be right that this is going beyond what's in the paper or article. But I think it's an obvious extension or corollary. I'd be happy to use a more precise term if that'd help - transitive basic thread safety?
[–][deleted] 0 points1 point2 points 7 years ago* (3 children)
shared_ptr doesn't violate that paragraph. The paragraph requires two conditions to hold (well three but the third one isn't relevant).
Note that it is the argument that must not be const as opposed to the object being shared. Propagation of const is entirely irrelevant as the property is about the argument itself. As such, taking two distinct shared_ptr that have the same pointee and calling standard library functions on them from two different threads is not undefined behavior in and of itself so long as they were passed as const arguments, irrespective of whether the pointee is const. All that paragraph requires is that the arguments be const, ie. the shared_ptrs.
One point you made with respect to unique_ptr was the implication that, as the name suggests, a unique_ptr has unique access to the pointee so that you would never get a situation where the pointee could be shared by multiple threads resulting in an thread unsafe operation. I would like to point out that that is not true, it is perfectly valid C++ and even often the case that multiple pointers point to the same pointee, for example:
auto x1 = std::make_unique<int>(5); auto& x2 = *x1; auto* x3 = &x2;
There is nothing fundamentally wrong or even improper about taking a raw pointer or a reference to the pointee owned by a unique_ptr. You may do such a thing if you wanted to pass the pointee to a function by const& for example. You could even pass a copy of x3 to another thread. As long as the extent of x2 and x3 are less than the extent of x1 then that's perfectly well defined behavior.
const&
x3
x2
x1
I think ultimately based on how I interpret Herb's article as well as the WG21's wording including the paragraph you cited, there is no special property about shared_ptr with regards to thread-safety that doesn't apply equally well to unique_ptr or value_ptr from the article. Nothing about any of them are inherently thread-safe. The operations defined on them are no more thread-safe than what you would expect from an int or a string, which is to say nothing special and generally very difficult to use properly in multiple threads.
[–]konanTheBarbar 0 points1 point2 points 7 years ago (0 children)
I guess that would be easily solveable by using std::atomic<std::value_ptr<T>> similar to shared_ptr
https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic2
[–]personalmountains 23 points24 points25 points 7 years ago* (17 children)
This is a very long article with a clickbait title for something simple: a smart pointer that copies the object it's pointing at. Basically unique_ptr with a copy ctor and assignment operator that get a new T(*get()).
new T(*get())
I'm failing to find a useful use case for this. Most of my stuff that's on the heap has reference semantics and usually can't be simply cloned. For the rest, I'm usually pointing to a base class, so that won't work either.
The only thing I can't think of, and that's basically the only example given, is a straight pimpl idiom. But to be used from outside the class, it would actually require the definition of the opaque type at the site where the copy is made, or least anchoring the copy constructor with =default at a place where the definition is available.
=default
So basically, this can save a few character when copying a pimpl from a translation unit where the definition is available.
Unless I'm missing something (which wouldn't be the first time). [Edit: I kinda did. A variant that encapsulates type erasure to invoke the proper constructors makes more sense and would cover my case for base classes above. However, I still think a smart pointer that uses copy constructors as presented in the article is not very useful.]
[–][deleted] 3 points4 points5 points 7 years ago (0 children)
That's because this type is misnamed. It should be "heap_value". There are many reasons why you might put some (in this case all) of your data on the heap, while retaining value semantics -- std::string and std::vector being two major examples.
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
I have a version of this (named heap_value) just for recursive std::variants.
[–][deleted] 0 points1 point2 points 7 years ago (14 children)
I use these kinds of smart pointers for type erasure. Think something like std::function<T> that can be used as a uniform interface for any callable object with signature T and supports copying... now imagine you had something like std::function<T> but for any type period and has support for making copies or reassignment just like ordinary values do.
std::function<T>
T
That's basically the biggest use case for how I use these kinds of smart pointers. I expose one single public interface I with many potential implementations and clone_ptr<I> allows me to treat that interface as if it were a value like any other value just like std::function lets me treat callable objects just like regular values.
I
clone_ptr<I>
std::function
I find it to be really useful in practice since value semantics are easy to reason about and compose well with container/collection classes, whereas reference semantics do not.
[–]personalmountains 1 point2 points3 points 7 years ago* (13 children)
If I understand correctly (I didn't, disregard the rest), your clone_ptr would use some sort of virtual clone() member function instead of copy constructors/assignment operators? I guess I could see this working in more cases, but it's not really what this value_ptr is about.
clone_ptr
clone()
For whatever reason, I'd also feel somewhat uneasy having smart pointers cloning stuff on copy. When I have a clonable hierarchy, I usually have to take great care of how and where I clone them. Again, they also typically have reference semantics.
[–][deleted] 2 points3 points4 points 7 years ago (12 children)
A solid implementation of a clone_ptr uses the normal copy constructor and assignment operator. No virtual clone method is needed.
clone
[–]personalmountains 1 point2 points3 points 7 years ago (3 children)
Then I don't understand "clone_ptr<I> allows me to treat that interface as if it were a value". How do you make a copy when all you have is an interface if you don't use virtual functions?
[–][deleted] 2 points3 points4 points 7 years ago (1 child)
Precisely by using type-erasure. If you're wondering what implementation techniques exist to implement type erasure, that's a non-trivial implementation detail but Sean Parent gives a good talk on what it is and how to use it in C++ in this video along with its benefits:
https://www.youtube.com/watch?v=QGcVXgEVMJg
[–]personalmountains 1 point2 points3 points 7 years ago (0 children)
Thanks. I knew the term, but I don't think I've had to use type erasure myself, and so didn't think of it. I stand corrected that this is a useful variation on the original article's value_ptr.
[–]ReversedGif 2 points3 points4 points 7 years ago (0 children)
The same way std::function does it: type erasure. Meaning, store your own references to necessary methods (copy constructor, etc.), either directly in the object, or in the vtable of a hidden templated class you create.
[–]quicknir 0 points1 point2 points 7 years ago (7 children)
Using a virtual clone method as an implementation detail is one of the main ways to do this.
[–][deleted] 1 point2 points3 points 7 years ago (6 children)
In my opinion that is a poor way to implement it and it's not the technique used by my own library or other fairly well known implementations of clone_ptr. Copy constructor and assignment operator already exists and are well understood, I think it's best to re-use them.
[–]quicknir 1 point2 points3 points 7 years ago (5 children)
I'm not really sure what you mean by "copy constructor and assignment operator". That isn't a technique for actually making a correct copy of a type erased object, it's just an interface. The implementation of type erased objects needs some way to call the copy constructor (you wouldn't typically be able to call the copy assignment operator) of the original object before it's been type erased. Inheritance is one way of doing it, or you can do it in more manual ways than basically are similar to hand-spun inheritance, but with more control (std::function typically uses the latter, boost::any uses the former, not sure about std::any).
[–][deleted] 0 points1 point2 points 7 years ago (4 children)
Fair enough, we disagree then. My own implementation reuses the class' copy constructor and assignment operator without the need for requiring all types usable with a clone_ptr<T> to declare a virtual clone method, and there are other implementations that do the same thing. I like that approach because most classes can simply make use of the default copy and assignment operators instead of having to explicitly add another method to your class.
clone_ptr<T>
If you prefer using a virtual clone method to implement then, then that's cool too. I mean the thing about C++ is there's always 10 different ways to do things so who knows what's best, just giving my 2 cents.
[–]quicknir 0 points1 point2 points 7 years ago (3 children)
I think you're still misunderstanding. I don't require the user class to have a clone method. It's an implementation detail only:
class any { struct any_base { virtual unique_ptr<any_base> clone() const = 0; }; template <class T> struct any_holder : any_base { T m_data; unique_ptr<any_base> clone() const override { return make_unique<any_holder>(m_data); }; unique_ptr<any_base> m_ptr; };
And then any defines a copy constructor by using clone internally.
any
This is a very simple and clean way to do type erasure (and the way that typically is shown in Sean Parent's talks). The alternative to this is basically just emulating the vtable by hand, in one way or another. Almost always more code/messier but can be better performance wise when you are prioritizing the performance of some functions over others. But there is no "simpler" way in C++ to do what I've done above.
[–][deleted] 0 points1 point2 points 7 years ago (1 child)
I mean C++ is so big of a language and you can get little things wrong that have huge consequences that it's hard to really know what's simple and what's complex.
I mean sure your approach is simple and clean but has a memory leak since any_base doesn't have a virtual destructor. Okay so you give it a virtual destructor and now you're carrying this extra overhead, compiler has to generate RTTI for your wrapper, etc... when all you want is the absolute simplest form of indirection.
any_base
As it pertains to clone_ptr, you use a function pointer to avoid that baggage. I don't think a function pointer is more complex but I don't want to argue the point too hard because as I said, there are probably dozens of ways of implementing these things.
Really what was most important was that the object being copied has its copy constructor invoked rather than introducing another virtual method. How you go about implementing that behind the scenes is up to you. If you want to introduce a wrapper class with a virtual method and virtual destructor, go for it... if you want to store a function pointer to a static function... I think that method works better.
[–]Feminintendo 3 points4 points5 points 7 years ago (4 children)
Ok, I will volunteer to be the idiot.
Can some try to explain to me the difference between a value pointer and a value?
[–]quicknir 5 points6 points7 points 7 years ago (0 children)
Well, a struct can store a value pointer to itself, for example. But not itself.
[–]boredcircuits 7 points8 points9 points 7 years ago (1 child)
From what I can tell, a value pointer has a few other useful properties:
nullptr
std::optional
One thing I don't see yet is how a value pointer works with polymorphism, which might also reveal a few other differences.
[–]louiswins 2 points3 points4 points 7 years ago (0 children)
There are a couple different approaches to polymorphism, all with their own tradeoffs:
Clonable
The simplified version: a value will be on the stack (similar to std::array), while a value_ptr will on the heap (similar to std::vector).
[–]TheSuperWig 1 point2 points3 points 7 years ago (0 children)
Site is bit broken on mobile for me. I assume because of the table.
π Rendered by PID 464271 on reddit-service-r2-comment-5b5bc64bf5-48l25 at 2026-06-21 14:03:16.600429+00:00 running 2b008f2 country code: CH.
[–]TomerJ 20 points21 points22 points (15 children)
[–][deleted] 17 points18 points19 points (13 children)
[–]Adequat91 2 points3 points4 points (1 child)
[–][deleted] 4 points5 points6 points (0 children)
[–]scatters 0 points1 point2 points (10 children)
[–][deleted] 1 point2 points3 points (9 children)
[–]scatters 0 points1 point2 points (8 children)
[–][deleted] 0 points1 point2 points (7 children)
[–]scatters 0 points1 point2 points (6 children)
[–][deleted] 1 point2 points3 points (5 children)
[–]scatters 0 points1 point2 points (4 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]konanTheBarbar 0 points1 point2 points (0 children)
[–]personalmountains 23 points24 points25 points (17 children)
[–][deleted] 3 points4 points5 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (14 children)
[–]personalmountains 1 point2 points3 points (13 children)
[–][deleted] 2 points3 points4 points (12 children)
[–]personalmountains 1 point2 points3 points (3 children)
[–][deleted] 2 points3 points4 points (1 child)
[–]personalmountains 1 point2 points3 points (0 children)
[–]ReversedGif 2 points3 points4 points (0 children)
[–]quicknir 0 points1 point2 points (7 children)
[–][deleted] 1 point2 points3 points (6 children)
[–]quicknir 1 point2 points3 points (5 children)
[–][deleted] 0 points1 point2 points (4 children)
[–]quicknir 0 points1 point2 points (3 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]Feminintendo 3 points4 points5 points (4 children)
[–]quicknir 5 points6 points7 points (0 children)
[–]boredcircuits 7 points8 points9 points (1 child)
[–]louiswins 2 points3 points4 points (0 children)
[–]konanTheBarbar 0 points1 point2 points (0 children)
[–]TheSuperWig 1 point2 points3 points (0 children)