11 ms·
Near-duplicate features of C++ (2017)
- earenndil 7y agoSome of these absolutely makes sense and are justified; others...are actually sane to have in c++. For instance: > int foo(void)/int foo() In c, int foo() means that foo takes any number of args; c++ rightfully realised that that was stupid and removed that feature, which means int foo() can now be used to mean foo takes no args. Also, int foo(void) is illegal in c++. Varargs in c are a complete pita to use, not to mention they literally do something different from function overloading/default args. Constexpr is much nicer and safer to use than a macro. Using malloc and calloc to make class instances means you can have unconstructed objects, which is a Bad Thing, and while introducing a new operator to do that is not necessarily the best way to handle that, it's a perfectly valid way of doing so. Libc random is just garbage, and libc++ random is actually decent. setjmp/longjmp are more complicated to use than try/catch, and don't have all the same functionality. <iostream> functions are type aware (although really they should have used fmt). I'm no c++ apologist (it's an awful language), but this listicle is just...not great.
- wnoise 7y ago> Also, int foo(void) is illegal in c++. Uh, citation needed. It would make compatibility with C libraries harder for no good reason. I believe it is valid as both declaration and definition. Both g++ and clang++ accept it without even a warning.
- hermitdev 7y agoI dont know offhand if it's illegal, but it's certainly unnecessarily verbose. Likewise, every compiler I've used accepts it, but it's unnecessary. Also, maybe a difference in behavior if code is in 'extern "C"' or not. I'm not sure. I rarely directly deal with C libs and havent been doing C++ for about 6 months now.
- harry8 7y agoUnnecessary is a question of taste, right? foo(void) seems less likely to cause confusion to anyone who hasn't got that C vs C++ distinction uppermost in their mind - I didn't. Nobody knows C++, we all know a subset of it and a smaller subset than we think we do and actually use, despite pretty constant study! Anything you do that makes a reader less likely to be confused, to make it less likely that they will or should break their flow by looking up the rule, is a good thing (tm). C++ suffers from "macho coding" styles and ethos quite badly. "I /believe/ I understand this subtlety at this moment so anyone who doesn't is stupid." Even when we didn't understand it ourselves just last week we forget it(!) We fool ourselves into thinking anyone who hasn't got at least a decade of hacking C++ every day is unworthy of reading our code, possibly pretending that 6 months can attain that level of oneness with changing standards. I try to use popular and safer features without thinking about it and if I want to use something slightly less popular when there is a choice, I ask "what problem am I solving? Is lowering readability a price I'm happy to pay here?" Before charging ahead with it. I probably classify some of the latter as the former due to over-familiarity. The ideal C++ code is rapidly readable and understandable without extremely taxing effort by a smart highschool student with 2-3 months of C++ experience. (Note the use of the word ideal in that sentence). s/C++/any language/ is also applicable. Other than following the style of the project you're working on is there any reason to use a reference ever over say a const pointer? Or a const pointer to a const object? The syntax then makes it clear you're not dealing with a pass-by-value copy. Maybe in another world everything would be const by default and have to be marked mutable then references might go away - but C++ couldn't do that and compile C which explains /some/ of the tension inside the language between various C++ features. Shame they didn't make references const by default if they had to introduce them. And member functions defaulting to const and explicit constructors by default. Const construction by default etc. There was an opportunity lost a long time ago to tighten up everything that isn't legal C as far as possible with the programmer having the option with an additional keyword.
- hermitdev 7y agoI largely agree with what you say, but can you elaborate on what you mean by "macho coding" styles? I'm guessing youre referring to when one deigns venture into template metaprogramming. TMP is an area with 2 decades of experience, I can basically only do it with a copy of the standard and/or relevant reference material handy. Although I'd consider my C++ knowledge in the 95th percentile or so, I probably know less than 20% of the std lib well. I've read most of the +1200 pages of the C++11 spec, but ive not kept up to date since, sadly, because its no longer my daily language.
- kllrnohj 7y agoI think the problem is mostly in the tone of the opening paragraph and less in the list itself. By prefixing this with "Don’t automatically assume that C++’s situation is desirable, necessary, or inevitable." It seems to be trying to frame this as C++ having bad duplication. But many of the things listed are not actually strict duplicates at all - like pointers vs. references, since references cannot be null (yeah yeah you can force it but 'int& foo = nullptr;' doesn't compile, either). Which if you then read the explanations at the bottom tend to cover in a fairly non-biased way.
- skookumchuck 7y ago> references cannot be null void test() { int* p = 0; int& r = *p; } compiles without complaint.
- hermitdev 7y agoI've gotten into arguments about this in the past. As you've shown, references can be null, but theyre not supposed to be and are assumed nearly universally to not be. The argument comes down to when the undefined behavior occurs: is it at the deference to create the reference, or is it on the first memory access using the reference? The language pedants will say the former, but in practice, it's the latter. In practice, you'll likely be able to invoke a member function on a null pointer or reference, as long as that member doesn't directly or indirectly access data members, or virtual functions of the type. Obligatory, I dont recommend doing this or relying upon this behavior, it's just behavior I've seen in my 2 decades of debugging C++.
- kllrnohj 7y agoIt's mostly important in the context of codifying nullability. If a function returns a reference it's part of the contract that it doesn't return null. Similarly, if a parameter is a reference it's part of the contract that you can't pass it null. It doesn't mean a method that takes or returns a pointer must allow null as a valid value, of course, Optional<> is better for that. But standards-enforced non-null is a very practically useful aspect of references that differ them from pointers.
- chrisseaton 7y ago> Also, int foo(void) is illegal in c++. What makes you think that? I'm looking at C++ 17, 11.3.5 (4). > A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list. What are you looking at?
- earenndil 7y agoAh, my mistake. Still, though, it's unidiomatic and rarely (if ever) used.
- whyever 7y ago> libc++ random is actually decent. I disagree. It does not include a contemporary RNG, and seeding the only decent one correctly is ridiculously difficult.
- earenndil 7y agoAfaik it uses mt19937? While not as good as it could be; something like pcg would probably be better, that's still very adequate. As for seeding it's pretty easy. It is stupid boilerplate that should be in the stdlib, but it's not difficult. You read from /dev/urandom if on unix, or use cryptgetrandom on windows, xor with time and pid if you really want to, and that's it.
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- mhh__ 7y agoDuplicate features, and thank god they exist: References, for example, have probably stopped millions of pointer arithmetic bugs of the years. Also, this should be viewed as C++ features C doesn't have: It's 2019 C, shouldn't be accepted anymore
- syockit 7y agoReference is among one the things I really want to be included in C. Does it break anything if it's introduced to the standard? On the other hand, I still prefer C to C++ mainly due to the compile time (an incremental compile in a typical large C project I deal with takes a second or so, while C++ takes 3-4 seconds). C++ doesn't have to be slow, as long as you use the needed features. But idiomatic C++ means you'd be using STL, class inheritance, virtuals, operator overloading, templates and constexpr and stuff, all of which contribute to longer compile times.
- mhh__ 7y agoI'd prefer longer compile times over runtime issues: Smart pointers are cheap, and easy to use now. C++ compile times are largely due to the absolutely ridiculous import system C++ forces you to use. Precompiled headers can eliminate a huge amount of C++ compilation time. The obvious solution is to avoid C++ when making new codebase, but that's easier said than done.
- tzhenghao 7y agoWell, one might grok C++ with the same perspective the author had, but I think C++, and especially C++17, make the language much safer and friendlier for beginners. C++17 for example is a big enough departure from pre C++11 days. If you stick to the bleeding edge, it doesn't look anything close to C at all. Author has a point there, but maybe, just maybe, we won't see "new"s or "delete"s in most future codebases? (we have smart pointers now) Or non-intuitive macros (yay constexprs!) I see these as stepping stones from C to where we are today without breaking everything at once or doing it with a whole other programming language.
- otabdeveloper2 7y ago> maybe, just maybe, we won't see "new"s or "delete"s in most future codebases? I haven't seen 'new' or 'delete' in the wild for a decade now. (Well, except for various legacy libraries or student code on Github.)
- geezerjay 7y agoQt code uses 'new' extensively because Qt components take ownership of components and manage memory allocation automatically.
- hellofunk 7y agoWhat you describe is still common practice in the language, but the mechanisms no longer use a new or delete to achieve that.
- roel_v 7y agoMe too. I've been writing pretty much only C++ for 20 years, and if I'd go back and count, I think I'd have maybe a dozen times where I used new/delete, none of those in the last 10 years. Like all languages that are actually used, there is much one can complain about in C++, but claiming that one needs a lot of manual memory management is done mostly by people who haven't written much if any C++.
- prewett 7y agoThe author missed an opportunity on the heap allocation section. Now you aren't even supposed to do `new`, but rather std::shared_ptr<...> or std::unique_ptr<...> (as appropriate). Except that you generally create them with std::make_shared() and std::make_unique(), so that adds another 4 items there. And then you have the fun of passing those to a function. Do you pass by value (shared_ptr) or by reference (I believe you do not) or pass a naked pointer (when you need to pass a unique_ptr to a function that uses, but does not modify or cache the pointer, if I remember correctly). And then suppose you want to give away your unique_ptr, that's fun. And if you want to deallocate your shared_ptr that's part of a cycle, you'll need to either use a weak pointer or manually reset it.
- geezerjay 7y ago> Now you aren't even supposed to do `new`, but rather std::shared_ptr<...> or std::unique_ptr<...> (as appropriate). Apples and oranges. Smart pointers are wrappers over raw pointers. They extend functionality, but are not the same. > Except that you generally create them with std::make_shared() and std::make_unique() Again, apples and oranges. You're confusing factory functions that wrap memory allocation for convenience with actual memory allocation. At most you could only complain that those factory methods duplicate the role of constructors, which would be silly. > And then you have the fun of passing those to a function. Do you pass by value (shared_ptr) or by reference (I believe you do not) or pass a naked pointer (when you need to pass a unique_ptr to a function that uses, but does not modify or cache the pointer, if I remember correctly). There is no duplication in your examples. You are just unaware of how those functionalities are used.
- nitwit005 7y agoThe tone of this is a bit silly. The main reason C++ was a success was due to the backward compatibility with C. That backward compatibility has (fairly obvious) downsides. Objective-C has the same issue, for the same reasons.
- 2bitencryption 7y agoSay what you will about c++, but it's the only language I know where you can declare classes as "friends" of one another.
- hellofunk 7y agoIt’s there for very rare purposes, and it’s considered a code smell if you ever use that feature.
- cisomag 7y agoI am still getting error.
- starchild_3001 7y agoUpdates/upgrades are justified. Using old style in new code, often, isn't.
- xhgdvjky 7y agoHerb Sutter has said again and again that his goal is to create a language that allows you to write less even though the committee is adding stuff. this fits with their goal of backwards compatibility. I don't see an issue
- Ace17 7y agoThe intent of the author is not very clear. Of course there are duplicate features, that's an obvious downside to keeping backward compatibility while still allowing improvement. If two equivalent/overlapping features were introduced in the same C++ version, then, yes it would be an indicator of a faulty design process.
- hellofunk 7y agoC++ is a more type safe language than C, and some of these “duplicated“ features are actually adding safety to the C versions. Most of these “duplications“ are quite in line with the C++ philosophy and are there for a good reason, reducing countless bugs and making code safer. And comparing a function pointer to a lambda expression is quite laughable.
- de_watcher 7y agoFrom the definition of the backward compatibility you get "old features still work while the new features that do the same thing work too".
- nayuki 7y agoThanks to everyone for the feedback. Here are my aggregated responses: • I feel that many commenters missed the fact that I was writing about NEAR-duplicate features of C++; I never said they were identical. But these features overlap so much that often all the alternatives are applicable in a real-world situation, and the choice becomes somewhat arbitrary, and you tend to see divergence between different coders and over the years. • I'm surprised to see that no one said anything like "Indeed, I do see these near-duplicate features in the C++ codebase that I work with. And it bothers me because I had to learn two things instead of one, and we have no stylistic consistency". • Some people expressed doubts about why I wrote the article. My intent and tone are clearly exhibited in the opening three paragraphs of the article; please reread them fully before judging. • Many people dwelled on the difference between references and pointers. I firmly support references and use them in my published code. But I've seen many people who learn C++ after C, and they try to use C-style pointers for as long as possible to avoid learning the new, native C++ feature which is much safer. Hence you cannot avoid seeing pointers in C++ if you read/edit code that come from diverse sources. • Many of my bullet points received no comments. I take it that either no one cares, or no one recognizes these points. For example, is it really sane for a language to have 3 ways of initializing a variable? (int i = 0; int j(1); int k{2};) • A subtread about const-by-default is something I agree with, though the syntax would mismatch semantics in C. Regardless, Rust is a relatively new language with nearly all of C++'s powerful features, and indeed it implements immutable-by-default. • I used new/delete in C++ in my early days, as a naive coder coming from C and Java with their manual management of memory allocation. But now I avoid those and rely on std::vector, std::unique_ptr, and RAII, which are safer and more concise. • (Previous thread: https://www.reddit.com/r/cpp/comments/6clwkq/nearduplicate_features_of_c/ https://www.reddit.com/r/cpp/comments/6clwkq/nearduplicate_f... )