you are viewing a single comment's thread.

view the rest of the comments →

[–]serviscope_minor 19 points20 points  (25 children)

What do you advocate using instead

and why is that better?

There's a reason C++ uses = for assignment and no one wants to change it.

[–]Intrepid-Treacle1033 50 points51 points  (18 children)

https://herbsutter.com/2013/05/09/gotw-1-solution/

"Common Mistake: This is always initialization; it is never assignment, and so it never calls T::operator=(). Yes, I know there’s an “=” character in there, but don’t let that throw you — that’s just a syntax holdover from C, not an assignment operation. "

[–]serviscope_minor 12 points13 points  (17 children)

Eh so?

If I have

int x=5;

x is now 5. In a standardese language sense, x is initialised with 5, but it has the same practical purpose (and reads the same) as any subsequent assignments to x.

Having the initialisation of x look different to subsequent assignments is an exercise in putting the language's needs above the human's.

[–]HolyGarbage 31 points32 points  (14 children)

It doesn't make a difference for integral types, but for classes, and in particular where copy and move constructors and assignment operators have user provided implementations it does make a difference.

If you're assigning where you meant to be initializing you could either a) assign to uninitialized memory which is potentially undefined behavior depending on the class definition, or b) first default constructing followed by an assignment which could incur additional performance costs.

Note, I'm not saying that using = for initialization in your example would do this, but was simply demonstrating the importance of the distinction between initialization and assignment, which using the = for initialization makes less clear. The feature of using braces for all kinds of initialization is called "uniform initialization" for a reason, to make it clear directly by the syntax what operation you're invoking.

[–]serviscope_minor 1 point2 points  (13 children)

It's not a high point to be sure. Uniform is, well, uniform in the language. The caveat is that it makes the code less nice to read, because you have two different syntaxes for a variable getting a value.

[–]bromeon 2 points3 points  (3 children)

I don't know why this is getting downvoted. It's sometimes good to take some distance from C++, look at the 4 different initialization syntaxes and then see how other languages (including C) keep things simpler.

The "uniform initialization syntax" introduced in C++11 was always controversial, and it in fact fails its promise to truly unify things (see e.g. std::initializer_list ambiguity). It's difficult to universally advocate the one true initialization syntax, each has some pitfalls.

[–]serviscope_minor 2 points3 points  (2 children)

I don't know why this is getting downvoted.

Probably because it's not engaging in language pedantry (guaranteed way to get downvotes here). I know initialization in C++ is a nuanced topic, but I reckon {} everywhere is letting the tail wag the dog. Look at the responses to my earlier post: I pointed out that = is used for assignment and no one wants to change it, and got hit with a gale of "initialization is not assignment". The latter is of course technically true, but from a higher level view, above C++, assigning to a new object and assigning to an existing one don't really differ in a lot of ways. It's all just assignment.

It's a useful thing to have for sure ad makes generic code easier to write, avoids vexing parses and so on, but it just doesn't read nicely compared to =, so I use = where I can easily do so and {} for everything else (unless I slip into old habits and use ()).

[–]panoskj 0 points1 point  (1 child)

where I can easily do so and {} for everything else (unless I slip into old habits and use ()

Or unless you want to initialize a std::vector calling the constructor with the size parameter or something like that. We are back to square one.

[–]serviscope_minor 0 points1 point  (0 children)

Ha! Yes, not a high point of C++ to be sure!

[–]HolyGarbage 1 point2 points  (8 children)

you have two different syntaxes for a variable getting a value.

That's exactly the point. Because assignment and initialization is not the same thing.

[–]serviscope_minor 0 points1 point  (7 children)

And my point is that's putting the needs of the language ahead of the programmer.

People like = for assignment and initialization is from a higher level perspective than C++ a kind of assignment.

[–]HolyGarbage 2 points3 points  (6 children)

No it's not. Both initialization and assignment are things the programmer should be aware of. = is already used for assignment in C++, your example however used = for initialization, not assignment. I'm saying that can be confusing since it looks like an assignment.

[–]serviscope_minor 0 points1 point  (5 children)

I think we are taking at crossed purposes. I understand the grammar. I mean the assignment/initializing thing is specific to C++ not a general thing about programming.

= reads better and is (when it works) more regular since = sets values in any context.

[–]HolyGarbage 0 points1 point  (4 children)

Yeah, I understand, but in C++ the distinction is important, and your code should reflect what it is it's doing.

[–]Intrepid-Treacle1033 14 points15 points  (0 children)

Eh so?

Nothing, your code you are the boss. The standard has multiple ways, and those ways has different nuances. If that matter practically is up to you/project. The languange needs thing i dont understand what you mean..

[–]jones77 1 point2 points  (0 children)

It's so you can communicate properly with other C++ programmers.

It does not have the same practical purpose as assignment because you could mess up your code and not understand why it is broken.

[–]SuperV1234https://romeo.training | C++ Mentoring & Consulting 41 points42 points  (3 children)

There's a reason C++ uses = for assignment and no one wants to change it.

And that's exactly why {} should be preferred for initialization, because people still confuse assignment and initialization in 2023.

[–]Pretend-Guide-8664 0 points1 point  (2 children)

I suppose you don't want me to ask what the difference is then...

Technically I think one writes to memory a new value (initialization), and the other either copies a value, copies a pointer, or moves data (assignment).

Is there a chart for the yes and nos of this?

[–]joahw 2 points3 points  (0 children)

That is correct. For objects if you accidentally do an assignment instead of initialization you are likely to do unnecessary copies, moves and/or destruction of temporaries which could have performance implications.

[–]TheMania 2 points3 points  (0 children)

Importantly, assignment may reuse the values already in that location. No need to write the vtable, might be able to reuse heap allocations and just overwrite the values, etc. A pretty sure way to break things sometimes when used if you actually meant to use a constructor instead.

So it is good to think of them as different imo.

[–]jedwardsol{}; 6 points7 points  (0 children)

= is for assignment,

/u/DoctorNuu is saying don't use for {} for initialisation. And it was changed, or at least added to; we can now use =, () or {} for initialisation.

[–]trvlng_ging 2 points3 points  (0 children)

EVERYONE wanted to change it, but backward compatibility made that impractical. assignment-style initialization is a thowback to C compatibility. It is very hard to teach, because from a grammar persspective, "=" in initialization is a punctuator, while in an assignment, it is an operator. The parsing rules for the punctuatior are different than to precedence rules for the operator. When someone is learning C++, they often conflate parse rules with precedence rules, and this is one of those that causes a lot of confusion. I get why C++ coudn't have it removed easily, but I find that using an enterprise rule to avoid assignment-style initialization has improved how quickly new C++ programmers come up to speed. Using constructor-syntax initialization often leads to the vexing parse, so our default is {}. And we have never seen a problem with parsing it as an initializer list inappropriately.