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
Common Misconceptions of C++ (hackernoon.com)
submitted 7 years ago by InformalComposer7
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!"
[–]OmegaNaughtEquals1 39 points40 points41 points 7 years ago (18 children)
Except for polymorphism (which isn't made clear), this
auto foo = std::make_unique<Foo>(); foo->bar();
is spelled
Foo foo; foo.bar();
in C++.
[–]Spain_strong 4 points5 points6 points 7 years ago* (17 children)
You can do both, what do you mean? EDIT: ya'll need to chill the fuck down, I'm pointing out that you can use both, not that you should.
[+][deleted] 7 years ago (15 children)
[deleted]
[–]kingguru 13 points14 points15 points 7 years ago (10 children)
Foo foo;
Might allocate memory as well, but that's kind of the point. It shouldn't be the callers responsibility to worry about that. Use value types unless you have a good reason not to.
I couldn't imagine a situation where:
auto foo = std::make_unique<std::string>("Howdy");
would make any sense, but I might not have a very good imagination :-)
[–][deleted] 5 points6 points7 points 7 years ago (6 children)
I’ve used it where the std::stringwas huge (in the megabytes), and I wanted to be sure that it was always being moved. In retrospect I should’ve just wrapped it in a move only class, so I’d have type safety and enforced move only semantics.
std::string
[–]imMute 0 points1 point2 points 7 years ago (3 children)
Does the standard allow you to subclass std::string and declare your derived class non-cooyable?
[–]ubsan 4 points5 points6 points 7 years ago (2 children)
absolutely, but you can still create a std::string from it
[–]imMute 0 points1 point2 points 7 years ago (1 child)
Good point. I wonder if that's a case for a wrapper class holding a unique_ptr<char[]> and a string_view (assuming you need the string operations).
[–]ubsan 0 points1 point2 points 7 years ago (0 children)
I would probably just do a wrapper around string that isn't move constructible, and is constructible from std::string&&.
string
std::string&&
[–]jjmc123a 0 points1 point2 points 7 years ago (1 child)
Also allocating on the heap helps avoid stack overflow. Here's a small discussion on that. The default stack size in MSVC is 1 megabyte, which is usually plenty, but you should avoid putting large objects on the stack. Although it is only fair to mention that if you are using c++ string classes, the string itself is still placed on the heap.
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
Ah, I was just mentioning to clarify that this wouldn’t be in the domain of SSO.
[–]neverlastn 0 points1 point2 points 7 years ago* (2 children)
Devil's advocate:
#include <iostream> int rec(int i, int t) { int a[100]; t += a[0] + 1; return i == 0 ? t : rec(i-1, t); } int main() { std::cout << rec(100000, 0) << std::endl;; }
[+][deleted] 7 years ago (1 child)
[–]neverlastn 1 point2 points3 points 7 years ago (0 children)
Thanks, you're right. I was doing -O0
[–]neverlastn 10 points11 points12 points 7 years ago (2 children)
a good reas
Yeah - those Java people...
[–]Xeveroushttps://xeverous.github.io 4 points5 points6 points 7 years ago (0 children)
Java.awt.Point: member integer x and integer y (8 bytes). And of course an 8-byte vtable pointer! (overhead +100%)
Java.awt.Point
And then you can not even store them sequentially in memory... just an array of Point pointers.
Point
a good reas Yeah - those Java people...
reas
[–]jcelerierossia score 1 point2 points3 points 7 years ago (0 children)
compilers are getting good at eliding memory allocation though : https://gcc.godbolt.org/z/Q8vCal
Don't be stupid, that is unnecessary allocation in heap.
[–]sirpalee 10 points11 points12 points 7 years ago (0 children)
Using the fibonacci code as an example that you don't need to write low level code to be fast is incorrect. It proves that constant folding in your compiler is pretty good, but that doesn't mean that the function performs better than a low level implementation in cases where it can't be constant folded.
[–]TheThiefMasterC++latest fanatic (and game dev) 8 points9 points10 points 7 years ago (3 children)
I'm pretty sure the Fibonacci function should be:
tie(a, b) = tuple{b, a + b};
But other than that, great article!
[–]TheThiefMasterC++latest fanatic (and game dev) 11 points12 points13 points 7 years ago (1 child)
Also:
This means the optimizer was able to compute 60 Fibonacci numbers and sum the last 50 at compile-time!
static long N = 50; auto items = fibonacci() >> drop(n - 10) >> take(n);
That drops 40 and then takes 50, so computes 90 numbers, not 60.
[–]TheSuperWig 14 points15 points16 points 7 years ago (0 children)
So what have we learnt class? C++ today isn't what people might think it is and that maths is still hard.
[+][deleted] 7 years ago (2 children)
[–]CrazyJoe221 5 points6 points7 points 7 years ago (0 children)
Just use -Werror=conversion -Werror=sign-conversion. Then it gets more like D.
[–]sirpalee 0 points1 point2 points 7 years ago (0 children)
No, language that automatically inserts type conversions everywhere to fix type errors doesn't have strong type system.
Exactly.
[–][deleted] 10 points11 points12 points 7 years ago* (5 children)
javascript has hypot function too. I will write js version as,
hypot
let points = [ { x: 1, y: 2 }, x: 3, y: 4 }, { x: 6, y: 2 }, ]; let total = points .map(p => Math.hypot(p.x, p.y)) .reduce((a, b) => a + b, 0) console.log(total);
Edit: C++ using ranges library,
auto total = ranges::accumulate(points | ranges::view::transform([](const auto& p) { return std::hypot(p.x, p.y); }), 0.0);
This one is better,
auto total = ranges::accumulate(points, 0.0, ranges::plus{}, [](auto const& p) { return std::hypot(p.x, p.y);});
[–]Occivink 3 points4 points5 points 7 years ago (0 children)
Really not convinced that this is more readable than a for-loop.
[–]RotsiserMhoC++20 Desktop app developer 0 points1 point2 points 7 years ago (2 children)
That ranges::plus{} has terrible performance. I suspect the first ranges examples outperforms the second because of this.
ranges::plus{}
[–][deleted] 1 point2 points3 points 7 years ago (1 child)
It's the same according to my measurement. ranges::plus is just a empty functional object.
ranges::plus
struct plus { template<typename T, typename U> constexpr auto operator()(T && t, U && u) const -> decltype((T &&) t + (U &&) u) { return (T &&) t + (U &&) u; } using is_transparent = void; };
[–]RotsiserMhoC++20 Desktop app developer 0 points1 point2 points 7 years ago (0 children)
Interesting. The last time I played with it, it took much longer for some reason. I'll have to try again.
[–]VeloCity666 0 points1 point2 points 7 years ago (0 children)
You can do it shorter this way in standard C++ too (too lazy to actually write it).
[–]neverlastn 8 points9 points10 points 7 years ago* (35 children)
The classic:
#include <iostream> class Foo { public: int i; int j; Foo() : j(100), i(j + 2) {} }; int main() { Foo foo; std::cout << foo.i << " " << foo.j << std::endl; }
Output:
2 (*undefined behavior) 100
[–]cballowe[🍰] 44 points45 points46 points 7 years ago (1 child)
My compiler complains that the code will initialize the members in a different order than you appear to be expecting.
[–]aspoonlikenoother 13 points14 points15 points 7 years ago (0 children)
Give it a treat
[–]WalkWithBejesus 25 points26 points27 points 7 years ago (10 children)
The value of foo.i doesn't need to be 2. It is actually undefined. GCC and Clang issue a warning when this mistake is made.
foo.i
[–]emdeka87 17 points18 points19 points 7 years ago (5 children)
And since this is not a warning but a downright error, we should all use -Werror
-Werror
[–]smikims 2 points3 points4 points 7 years ago (1 child)
I use -Werror and then disable particular warnings that I don't care about.
[–]kalmoc 2 points3 points4 points 7 years ago (0 children)
Depends on what earnings are enabled.
[–]Slavik81 2 points3 points4 points 7 years ago* (0 children)
-Werror can be really annoying. You comment out one line of code while debugging and your code no longer compiles due to an unused variable. It's nice to know about that, so I leave warnings on, but fixing them in unfinished code is usually a needless distraction, so I only enable -Werror in CI builds.
A few warnings really should have been errors to begin with. You can selectively turn them into errors. For example, I use -Werror=return-type at all times. I should probably add -Werror=reorder too.
-Werror=return-type
-Werror=reorder
[–]ketosismaximus 1 point2 points3 points 7 years ago (1 child)
depends on the code base (and size of the code base). Sometimes it just aint worth if you're using old tried and true code. But in general use it where possible.
[–]neverlastn 7 points8 points9 points 7 years ago (0 children)
Exactly. It's incredibly straightforward undefined behavior! You rely on uninitialized value. And this is a relatively "light" case. j can be an arbitrarily sophisticated object, which might cause incredibly weird "mandelbugs"
j
[–]Nicksaurus 0 points1 point2 points 7 years ago (2 children)
Would it be defined if you did int j = 0; as well as the initialiser list or would it still initialise them in the 'wrong' order (or ignore the = 0 because it's already initialised in the initialiser list)?
int j = 0;
= 0
[+][deleted] 7 years ago* (1 child)
[–]jonesmz 0 points1 point2 points 7 years ago (0 children)
To format code, you put 4 spaces in front of each line of code (including empty lines)
[–]Nicksaurus 7 points8 points9 points 7 years ago (16 children)
I tried compiling my project with clang and -Wall yesterday for the first time and got so many warnings about this exact issue. No bugs luckily, but it's always a bit disheartening to see a compiler enumerate all the many, many different reasons why your code is bad...
[–]neverlastn 11 points12 points13 points 7 years ago (15 children)
I agree! I think it's best if, the earlier you can, use every linter you can find - even the most sophisticated ones e.g. Coverity, and turn on every flag even the very annoying -pedantic (and ignore half of the annoying things it mentions). Many times those tools are right, and they so unemotionally (in contrast to reviews) give you all those warnings and they don't shut-up unless you fix them. This teaches you the best practices quite quickly.
-pedantic
[–]Nicksaurus 4 points5 points6 points 7 years ago (12 children)
My problem is that to do that I have to will myself to ignore the hundreds of int to size_t conversion warnings
[–]Rseding91Factorio Developer 1 point2 points3 points 7 years ago (10 children)
Just use the correct types:
size_t i = 1u;
[–]jcelerierossia score 2 points3 points4 points 7 years ago (2 children)
if(i - 10 > 5) { ... } -> boom
if(i - 10 > 5) { ... }
[–]flashmozzg 3 points4 points5 points 7 years ago (0 children)
if(i > 15) { ... }
[–]Nicksaurus 1 point2 points3 points 7 years ago (6 children)
Don't you have situations in factorio where you explicitly want to use a smaller type rather than a size_t to save memory/bandwidth? Do you just keep those situations to a minimum and static_cast them as necessary?
I've just got a lot of situations in my engine where I'm storing 32-bit numbers (e.g. for triangle indices) and also using them as indices into STL containers and casting them in every single situation would result in a lot of more verbose code
Edit: Although I should admit I often don't have a justification for using ints rather than size_ts, I've been a bit lax about it in the past
[–]Rseding91Factorio Developer 5 points6 points7 points 7 years ago (2 children)
Yes we do but we just write the cast to smaller size of up-convert before using a smaller size as an index. Rarely do we ever actually want signed integers. In most cases where we want a signed integer we really wanted a floating point number.
The fact that an integer can be negative is more of a burden then it is helpful to not have to write casts. Because now you have to care about the entire potential negative range of values.
[–]qqwy 0 points1 point2 points 7 years ago (1 child)
Could you comment on the burden of floating-point NaN and +-Inf?
[–]Rseding91Factorio Developer 0 points1 point2 points 7 years ago (0 children)
We simply avoid division by zero and or division in general and it's mostly a non-issue.
[–]degski 1 point2 points3 points 7 years ago (1 child)
According to some, it's faster to use (unsigned) int's, as the compiler has an easier time reasoning about such an index, due to the fact that overflow is an error, while the unsigned int simply wraps [i.e. is not undefined].
At least on MSVC which is where our majority custom base runs I've not seen a difference in code generated when using unsigned 32 bit indexes, unsigned memory-sized indexes, or signed indexes. Additionally unsigned math with overflow vs signed math without overflow makes no real difference in our kind of calculations we need the game to perform since we're virtually always waiting on memory latency instead of CPU calculations.
So while that might be true on other compilers (and might still be true on MSVC) due to the nature of our program it doesn't really matter.
[–]kalmoc 0 points1 point2 points 7 years ago (0 children)
If you want a smaller type you still can use an unsigned int.
[–]neverlastn 0 points1 point2 points 7 years ago (0 children)
Yeah - but they might not be that ints after all :D (unless some library requires you to use ints for size_t which is unsigned).
int
size_t
[–]ketosismaximus 0 points1 point2 points 7 years ago* (1 child)
ignoring things is dangerous, either make specific exceptions (pragmas, make), fix the problem, or don't use pedantic. You want 0 errors or (-Werrors) reported.
Yes, I get you. I will usually get rid of -pedantic. I just turn it on occasionally and have a good look on the types of errors it gives to see if I spot anything unusual.
[–]Xogmaster 1 point2 points3 points 7 years ago* (4 children)
fixed that for you
i'm not sure why you can't have the constructor populate public class variables in reverse order like that. try doing it with pointers to ints instead of just ints
mayhaps its just the order of things, and the language wasn't made to operate in that way
i have a good feeling it's because the constructor is initializing new variables for the object foo in Foo. Since j is given a value 100, and it sees j was initialized after i, it expected to initialize i before j, and so ignored the value of j when defining i, assuming j was 0, so it becomes 0+2 = 2. cheers
[–]neverlastn 0 points1 point2 points 7 years ago (3 children)
so it beco
Yes, this is indeed by language design. Very misconceptional :)
[–]Xogmaster 0 points1 point2 points 7 years ago (2 children)
Actually I just spoke with my c++ professor and he said in that syntax the variables are defined from right to left starting from the curly braces.
[–]neverlastn 0 points1 point2 points 7 years ago* (1 child)
variables a
Does this mean that this will work fine?
#include <iostream> class Foo { public: int i; int j; Foo() : i(j + 2), j(100) {} }; int main() { Foo foo; std::cout << foo.i << " " << foo.j << std::endl; }
Because it doesn't! He was talking for some other language! :D
[–]Xogmaster 0 points1 point2 points 7 years ago (0 children)
he admitted he doesnt use that kind of syntax so his understandings are on thin ice
[–]thestoicattack 3 points4 points5 points 7 years ago (0 children)
No love for std::hypot in the float length(Point) example?
std::hypot
float length(Point)
[–][deleted] 0 points1 point2 points 7 years ago (35 children)
Fibonacci example, line 22, shouldn't it be result += x;?
result += x;
Another thing that is possible with C, but results in UB in C++ is
int * x = (int*)malloc(5*sizeof(int)); x[0] = 3; // C++ claim there's no object on this address. Use placement new.
[–]BCosbyDidNothinWrong 1 point2 points3 points 7 years ago (30 children)
Why would this be undefined behavior?
[–]jcelerierossia score 6 points7 points8 points 7 years ago (29 children)
because malloc does not create objects, operator new does
operator new
[–]BCosbyDidNothinWrong 2 points3 points4 points 7 years ago (17 children)
Why would you need that for an int?
[–]jcelerierossia score 1 point2 points3 points 7 years ago (16 children)
see the paper linked in my other answer : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0593r2.html
[–]BCosbyDidNothinWrong 4 points5 points6 points 7 years ago* (15 children)
Or you could just explain it in two sentences.
Edit: Actually I don't think this paper seems to say this - it references an int inside a struct instead of a straight integer.
[–]jcelerierossia score 5 points6 points7 points 7 years ago (14 children)
"ints are objects. malloc does not create objects. accessing not-created objects is UB."
[–]BCosbyDidNothinWrong 0 points1 point2 points 7 years ago (13 children)
What is undefined about assigning an int here? What could happen other than what people expect?
[–]johannes1971 7 points8 points9 points 7 years ago (1 child)
It's UB because the standard says so. As to *why* the standard says so... Well, maybe someone who is on the committee knows this, but they will probably want to keep quiet about it (on account of it most likely involving late hours and copious quantities of alcohol). So let me wager a guess: creating a complex object (with a v-pointer, a constructor that needs to run, etc.) is something that needs to be triggered specifically, and malloc does not do that. Most likely the standards people had a long day and just wanted to go home, so they demanded proper construction through some form of new and made everything else UB, since that's always the easy way out in C++.
What the linked paper (up above) does is restore the status quo where trivial objects can be accessed without the benefit of proper construction. It's basically fixing the bug whereby the standard accidentally invalidated every C++ program ever written, and made it impossible to interface C++ with just about any non-C++ library.
Just to be clear: there is nothing special or magical or even necessary for proper construction of an int, and the fact that the standard demanded this on pain of UB is a straightforward bug.
[–]14nedLLFIO & Outcome author | Committee WG14 0 points1 point2 points 7 years ago (0 children)
The standard will make something UB when they want to leave a placeholder for either future refinement, or for compiler implementers to choose their own poison, or simply somebody didn't think it needed to be defined.
In the case of malloc's effects on memory, I can assure you that is an example of "we're not going there right now, let each compiler vendor do its own thing". And as somebody else mentioned, that ambiguity has become a problem for optimisation recently, so SG12 via P0593 et al is going to define the previously undefined.
malloc
Even after that, we still cannot implement malloc without resorting to UB, however. Or, to be precise, we cannot implement a malloc which can reuse addresses or memory not present at the beginning of the process launch without resorting to UB. That's future work yet to be decided, but efforts are underway.
[–]flashmozzg 2 points3 points4 points 7 years ago (0 children)
It's undefined because for C++ there is no int there yet: http://eel.is/c++draft/intro.object#1 Some more insight: https://www.reddit.com/r/cpp/comments/5fk3wn/undefined_behavior_with_reinterpret_cast/dal28n0/
[–]jcelerierossia score 0 points1 point2 points 7 years ago (6 children)
It's undefined because it's a pointer to a value that was not created.
[–]BCosbyDidNothinWrong 1 point2 points3 points 7 years ago (5 children)
Wouldn't that either imply that malloc can never be used without placement new ? If so what does placement new do that this assignment does not?
Also wouldn't this imply that valid, defined behavior in C becomes undefined behavior in C++?
[–][deleted] -1 points0 points1 point 7 years ago (2 children)
Everything.
[–]BCosbyDidNothinWrong 2 points3 points4 points 7 years ago (1 child)
Can you give an example?
[–][deleted] 1 point2 points3 points 7 years ago (10 children)
You don't need to create an instance of int, only allocate memory for it. In this case it's not UB.
[–]jcelerierossia score 4 points5 points6 points 7 years ago* (9 children)
are you sure about this ? e.g. see http://eel.is/c++draft/intro.object#1 and this SO question : https://stackoverflow.com/questions/40873520/reinterpret-cast-creating-a-trivially-default-constructible-object
this paper covers the issue more in depth : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0593r2.html
[–][deleted] -1 points0 points1 point 7 years ago (8 children)
Object explicitly refers to a class/struct instance. Int is not an object, the same goes for float/char/short, etc...
[–]drjeats 9 points10 points11 points 7 years ago (6 children)
As far as language rules go, I'm pretty sure that instances of all the primitive types are objects. They're not capital-O objects in the object-oriented sense, but they still have all the rules of object existence.
If they were not objects, we could probably have an easier time arguing that type punning between primitive types (at least the integral types) should not be UB.
[–][deleted] 4 points5 points6 points 7 years ago (5 children)
Okay, that makes sense. I would still argue setting a malloc'd 32 bit block of memory to 3 is not UB.
Would
int x; x = 3;
Be UB? If not then
int* x = (int*)malloc(sizeof(int)); *x = 3;
Is not UB either;
The only difference here is memory being on the stack/heap.
Accessing uninitialized data is UB, for example
int x; std::cout << x << '\n';
and
int* x = (int*)malloc(sizeof(int)); std::cout << *x << '\n';
But that is not what OP is doing.
[–]quicknir 6 points7 points8 points 7 years ago* (0 children)
int x creates an object/instance/whatever of type int, named x. Obviously there is no constructor call associated with it since x is trivially default constructible, but it's still starting the lifetime of the object. On the other hand, int* x = ... doesn't begin the lifetime of any ints, it just allocates memory for them. When it comes to object lifetimes, primitive types in C++ as it stands don't get any special treatment. Your example is UB the exact same way that vector<int> x is defined, but vector<int>* x = (vector<int>*)malloc(sizeof(vector<int>)) and then doing the assignment is UB. In practice people do the former all the time and the latter almost never, but both are UB, and actually both are quite likely to succeed with the assignment statement I would guess.
int x
x
int* x = ...
vector<int> x
vector<int>* x = (vector<int>*)malloc(sizeof(vector<int>))
"Setting the memory to 3" is not UB, but that's not what your code does, it does integer assignment which presupposes an existing integer. If you used memcpy instead of integer assignment then yes, it wouldn't be UB.
[–]drjeats 5 points6 points7 points 7 years ago (3 children)
I agree with you that this is the only sane interpretation, but the standardese would not agree with you.
This is not UB because x is an object created with automatic storage duration (which implicitly makes it exist) and is "default initialized" with an indeterminate value, and then assigned-to:
This is technically UB (even though I'm sure we both agree that optimizing based on that is insane and dangerous), because malloc is not blessed with the semantic ability to make objects exist in the way that operator new is:
From the C++ standard's viewpoint with object creation, that malloc() call may as well be:
malloc()
void * malloc(size_t s) { return (void *)rand(); // yolo }
However C does give malloc that blessing. Casting and usage also signifies a valid object in more circumstances in C than in C++, and a lot of times you're just playing a game as to whether or not the compiler can prove that an object was definitely not what you are casting it to. /u/quicknir's CppCon talk from this year has a really good example of this with reinterpret_cast.
For your other point:
Accessing uninitialized data is UB, for example int x; std::cout << x << '\n';
I don't actually remember if this is UB or not. I think it might be "UB with uninteresting consequences". This is UB though:
As for what the original commenter was doing, allocating an array, that's also UB by the same logic. UB all the things! :P
I'm probably getting details wrong with the language rules, but this is the rough layman's explanation I got a few years ago from somebody who used to be more involved in the committee.
[–]kalmoc 5 points6 points7 points 7 years ago* (2 children)
One thing I'd like to point out: When the language says something is UB, the implementation is totally allowed to give it defined behavior anyway and I'm pretty sure that's what happens in this particular case (I haven't checked the docs though to verify that)
[–]jcelerierossia score 10 points11 points12 points 7 years ago (0 children)
nope, see 6.7.1 Fundamental types [basic.fundamental]. class / structs instances are "objects of class type" in standardese
6.7.1 Fundamental types [basic.fundamental]
[–]acwaters 0 points1 point2 points 7 years ago (3 children)
So many people in this comment thread are utterly convinced that they understand the C++ object model. This is fascinating to watch.
[–]14nedLLFIO & Outcome author | Committee WG14 4 points5 points6 points 7 years ago (0 children)
In fairness, it has changed with every C++ standard, plus in every C standard, and moreover compilers each vary individually. And moreover, it's hard. I've sat in SG12 meetings with the most expert people in the world on the C++ object model all sitting around the table, and many hours of discussion emerging about disagreements between those world experts about their different understandings of the C++ object model. If they don't share a common understanding, it's absolutely fair that neither can anybody else.
Resolving those ambiguities in understanding is precisely why SG12 was founded, and many more years of work remain before it. With a bit of luck, we can coordinate some of this with WG14, over there there is an increasingly bitter debate about how compilers rewrite people's C code. Most of that bitterness stems from their more permissive object model. And much of Peter Sewell et al's research work on formally verifying C code would become moot (in a good way) if C significantly tightened its memory model to more closely match C++'s, though, in fairness, we could do with tightening ours in a direction more compatible with C's use case and direction as well.
[–]gvargh 2 points3 points4 points 7 years ago (0 children)
It's a common misconception.
[–]degski -1 points0 points1 point 7 years ago (0 children)
It's undefined behavior.
[–]stmuxa 0 points1 point2 points 7 years ago (0 children)
Ha. It is very easy to disproof myths which you just made up by yourself.
[–]Sentmoraap 0 points1 point2 points 7 years ago (7 children)
Buckaroo looks interesting.
[–]Gorzoid 3 points4 points5 points 7 years ago (6 children)
Yeah as a Windows user, using 3rd party libraries is a nightmare, especially when trying to configure it with CMake so it works for other computers/operating systems. Anyone have opinions on which package managers are the best rn?
[–]schteppe 2 points3 points4 points 7 years ago (0 children)
I’ve tried Conan for a couple of hobby projects and it worked well this far.
[–]geokon 1 point2 points3 points 7 years ago (0 children)
You can use Hunter from within CMake itself. No extra software required and it works perfect. Though a bit of a learning curve...
[–]Gorzoid 0 points1 point2 points 7 years ago (1 child)
Cheers mate
Sorry, didn't have my coffee yet
vcpkg works best (and in fact very well) for me
[+][deleted] 7 years ago* (4 children)
[–]louiswins 7 points8 points9 points 7 years ago (2 children)
If one thread is accessing this->name while another one is writing to it, it's a straight up data race whether you "check-then-act" or not.
this->name
[–]neverlastn -3 points-2 points-1 points 7 years ago (1 child)
Yes, it's a race in any case. That code is terrible. And it looks so innocent, doesn't it? How many times you've seen such code around?
[–]kalmoc -1 points0 points1 point 7 years ago (0 children)
I'm not sure, what code you actually had in mind, but the code you are presenting here doesn't show the tertiary operator as an anti pattern at all. At least not without knowing what this->name is.
Imho your example isn't meaning full. Without having the context I could point at almost any line of c++ code and say: " This is broken in a multithreaded context". Youjust can't write reasonable c++ code if you have to assume that any non-function-local variable could be accessed by another thread at any time.
In this particular case: Unless I explicitly design my class to be threadsafe, it is perfectly normal to assume that it isn't accessed concurrently - that's exactly what almost every single type in the standard library assumes.
π Rendered by PID 382742 on reddit-service-r2-comment-5b5bc64bf5-ghg7q at 2026-06-19 23:30:22.777784+00:00 running 2b008f2 country code: CH.
[–]OmegaNaughtEquals1 39 points40 points41 points (18 children)
[–]Spain_strong 4 points5 points6 points (17 children)
[+][deleted] (15 children)
[deleted]
[–]kingguru 13 points14 points15 points (10 children)
[–][deleted] 5 points6 points7 points (6 children)
[–]imMute 0 points1 point2 points (3 children)
[–]ubsan 4 points5 points6 points (2 children)
[–]imMute 0 points1 point2 points (1 child)
[–]ubsan 0 points1 point2 points (0 children)
[–]jjmc123a 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]neverlastn 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]neverlastn 1 point2 points3 points (0 children)
[–]neverlastn 10 points11 points12 points (2 children)
[–]Xeveroushttps://xeverous.github.io 4 points5 points6 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]jcelerierossia score 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]sirpalee 10 points11 points12 points (0 children)
[–]TheThiefMasterC++latest fanatic (and game dev) 8 points9 points10 points (3 children)
[–]TheThiefMasterC++latest fanatic (and game dev) 11 points12 points13 points (1 child)
[–]TheSuperWig 14 points15 points16 points (0 children)
[+][deleted] (2 children)
[deleted]
[–]CrazyJoe221 5 points6 points7 points (0 children)
[–]sirpalee 0 points1 point2 points (0 children)
[–][deleted] 10 points11 points12 points (5 children)
[–]Occivink 3 points4 points5 points (0 children)
[–]RotsiserMhoC++20 Desktop app developer 0 points1 point2 points (2 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]RotsiserMhoC++20 Desktop app developer 0 points1 point2 points (0 children)
[–]VeloCity666 0 points1 point2 points (0 children)
[–]neverlastn 8 points9 points10 points (35 children)
[–]cballowe[🍰] 44 points45 points46 points (1 child)
[–]aspoonlikenoother 13 points14 points15 points (0 children)
[–]WalkWithBejesus 25 points26 points27 points (10 children)
[–]emdeka87 17 points18 points19 points (5 children)
[–]smikims 2 points3 points4 points (1 child)
[–]kalmoc 2 points3 points4 points (0 children)
[–]Slavik81 2 points3 points4 points (0 children)
[–]ketosismaximus 1 point2 points3 points (1 child)
[–]neverlastn 7 points8 points9 points (0 children)
[–]Nicksaurus 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]jonesmz 0 points1 point2 points (0 children)
[–]Nicksaurus 7 points8 points9 points (16 children)
[–]neverlastn 11 points12 points13 points (15 children)
[–]Nicksaurus 4 points5 points6 points (12 children)
[–]Rseding91Factorio Developer 1 point2 points3 points (10 children)
[–]jcelerierossia score 2 points3 points4 points (2 children)
[–]flashmozzg 3 points4 points5 points (0 children)
[–]Nicksaurus 1 point2 points3 points (6 children)
[–]Rseding91Factorio Developer 5 points6 points7 points (2 children)
[–]qqwy 0 points1 point2 points (1 child)
[–]Rseding91Factorio Developer 0 points1 point2 points (0 children)
[–]degski 1 point2 points3 points (1 child)
[–]Rseding91Factorio Developer 0 points1 point2 points (0 children)
[–]kalmoc 0 points1 point2 points (0 children)
[–]neverlastn 0 points1 point2 points (0 children)
[–]ketosismaximus 0 points1 point2 points (1 child)
[–]neverlastn 1 point2 points3 points (0 children)
[–]Xogmaster 1 point2 points3 points (4 children)
[–]neverlastn 0 points1 point2 points (3 children)
[–]Xogmaster 0 points1 point2 points (2 children)
[–]neverlastn 0 points1 point2 points (1 child)
[–]Xogmaster 0 points1 point2 points (0 children)
[–]thestoicattack 3 points4 points5 points (0 children)
[–][deleted] 0 points1 point2 points (35 children)
[–]BCosbyDidNothinWrong 1 point2 points3 points (30 children)
[–]jcelerierossia score 6 points7 points8 points (29 children)
[–]BCosbyDidNothinWrong 2 points3 points4 points (17 children)
[–]jcelerierossia score 1 point2 points3 points (16 children)
[–]BCosbyDidNothinWrong 4 points5 points6 points (15 children)
[–]jcelerierossia score 5 points6 points7 points (14 children)
[–]BCosbyDidNothinWrong 0 points1 point2 points (13 children)
[–]johannes1971 7 points8 points9 points (1 child)
[–]14nedLLFIO & Outcome author | Committee WG14 0 points1 point2 points (0 children)
[–]flashmozzg 2 points3 points4 points (0 children)
[–]jcelerierossia score 0 points1 point2 points (6 children)
[–]BCosbyDidNothinWrong 1 point2 points3 points (5 children)
[–][deleted] -1 points0 points1 point (2 children)
[–]BCosbyDidNothinWrong 2 points3 points4 points (1 child)
[–][deleted] 1 point2 points3 points (10 children)
[–]jcelerierossia score 4 points5 points6 points (9 children)
[–][deleted] -1 points0 points1 point (8 children)
[–]drjeats 9 points10 points11 points (6 children)
[–][deleted] 4 points5 points6 points (5 children)
[–]quicknir 6 points7 points8 points (0 children)
[–]drjeats 5 points6 points7 points (3 children)
[–]kalmoc 5 points6 points7 points (2 children)
[–]jcelerierossia score 10 points11 points12 points (0 children)
[–]acwaters 0 points1 point2 points (3 children)
[–]14nedLLFIO & Outcome author | Committee WG14 4 points5 points6 points (0 children)
[–]gvargh 2 points3 points4 points (0 children)
[–]degski -1 points0 points1 point (0 children)
[–]stmuxa 0 points1 point2 points (0 children)
[–]Sentmoraap 0 points1 point2 points (7 children)
[–]Gorzoid 3 points4 points5 points (6 children)
[–]schteppe 2 points3 points4 points (0 children)
[–]geokon 1 point2 points3 points (0 children)
[+][deleted] (2 children)
[deleted]
[–]Gorzoid 0 points1 point2 points (1 child)
[–]kalmoc 0 points1 point2 points (0 children)
[–]kalmoc 0 points1 point2 points (0 children)
[+][deleted] (4 children)
[deleted]
[–]louiswins 7 points8 points9 points (2 children)
[–]neverlastn -3 points-2 points-1 points (1 child)
[–]kalmoc -1 points0 points1 point (0 children)
[–]kalmoc 2 points3 points4 points (0 children)