$ gcc -xc - <<<"int main(int argc, char **argv) { long long long a; return 0; }"
<stdin>: In function ‘main’:
<stdin>:1:45: error: ‘long long long’ is too long for GCC
> This label is the target of a goto from outside of the block containing this label AND this block has an automatic variable with an initializer AND your window wasn't wide enough to read this whole error message
Jokes often work with subverting expectations. In this case you're surprised by a message that doesn't belong and then you remember where it comes from and likely relate it with how frustrating those ever changing rules can be.
I thought it was funny because I've seen similar complaints from linters, e.g. clang-tidy's readability-identifier-length plus readability-identifier-naming, or pylint's invalid-name. (clang-tidy at least is smart enough to exempt loop counters.)
And on that day, I finally opened the Monolithic set of x86_64 programmer tomes, and finally figure out how to manually do linking.
You will be amazed how much of my skill with computers comes down to channeling Obsessive Defiance Disorder into digging into how to do what the compiler writers don't want to let me do, and doing it my way. With tests.
That's more like ++C. You need "ADD 1 TO COBOL RETURNING COBOL"... which elicits another C++ joke: that it would have been nice to get to use the better version, but someone used the wrong operator, so what we have is certainly complicated but probably just more of the same.
My favorite, best told while among C programmers involuntarily debugging some gnarly C++ is, "Man, I swear, the dude that invented C++ doesn't know the difference between increment and excrement."
Narrator: It's at this point Michael realized the futility of C++ and promptly learned Rust over a couple of beers pondering if he will ever survive the oncoming AI apocalypse.
This is one of the surviving improvements from JF Bastien's P1152 which was initially successful in deprecating most of the spurious use of volatile from C++ with a view to some day getting in there and actually doing MMIO properly.
Unfortunately too much of this will be unwound in C++ 23 because WG21 voted to un-deprecate all the volatile compound operators despite knowing nobody could even offer a rationale for why or how most of them would ever be correctly used.
P2327 would be in my "not angry just disappointed" category. Of course WG21 think rotten archaic C code should be valid C++ 23 and the belief from embedded devs who write this stuff that it's probably all fine despite no evidence whatsoever should be enough to sail through committee.
WG21 voted to amend the draft to un-deprecate all of the volatile compound assignments instead, at Kona IIRC.
#include <iostream>
using namespace std;
class BadProgrammer {
public:
void yep() {
delete this;
}
};
int main() {
auto x = BadProgrammer{};
x.yep();
cout << "You are a terrible engineer and should feel bad, but don't worry because this will never print." << endl;
return 0;
}
g++ -Wall -Wextra -Wpedantic main.cc # compiles just fine
clang++ -Wall -Wextra -Wpedantic main.cc # also compiles just fine
FWIW the behavior of delete on a pointer that isn’t either null or returned from new is undefined.
So a conforming C++ compiler doesn’t have to diagnose this mistake, and similarly the compiled program doesn’t have to do anything meaningful either. For example, just ignoring the delete and printing the message is as valid a result as the more useful crash at the site of the bad operation.
I was surprised to see it not mentioned in the post -- the most obvious reason this joke should be retired is not the reference to a television show but rather the modern practice of never using new or delete at all in C++ code. Modern C++ avoids these pitfalls and I think it's been 10 years since I've written the words the new or delete.
I frequently work with companies that have old, large codebases. A key requirement of the training in that environment is that attendees are able to read existing production code. In some cases that's over twenty years old and millions of lines of code. new/delete is just part of that reality. We teach them without encouraging their use.
You haven't programmed til you've come to the realization that billions of dollars worth of man hours are about to go down the toilet because of an assumption made 20 years ago, in a 4th order dependency, that you can't get rid of, and to rewrite is going to cost another couple million dollars, and spent a night with a bottle of whiskey wondering whether it's really all worth it.
Absolutely. I would also not use new/delete in that situation. It would depend on the audience whether they were still taught on a course, sometimes there is, and sometimes there isn't an educational purpose.
No, it’s not just theory. Like anything in C++, codebases and their styles widely vary. But my comment holds true for the vast majority of developers I have worked with over the last decade. With the exception of the special “placement new“ operator, it is nearly obsolete to use new and delete.
Hmm, I was at G until the recent decimation, and would have been surprised to see `new`, especially in new (heh) code, because it immediately raises the question of ownership, which means it costs time for every future reader.
Taking chromium as a proxy (though the style isn't identical), there are currently 5 or 6 times as many `make_unique` as `new`. (Some false positives on the word ‘new’ in strings, because I don't remember how to exclude them.)
We are talking about one very specific issue, the point of this thread is a joke about new and delete. And your response after evidence services against your position is, “what about all these other things?” Definition of whataboutism.
Nope, the whole issue is about modern C++ in practice versus slideware at conferences.
Also chromium code base is one example from many others, and it is so modern C++ that Google has finally decided to adopt Rust as only viable alternative to improving it.
Big G has plenty of samples that aren't so modern, specially on Android. Which by the way is also moving away from C++ instead of "modernising" it.
If you are going to work with a legacy codebase, then sure. My comment was more about fresh codebases, which are fortunately the only ones I've worked on.
I would argue it is not for me at least. In my 2 current C++ commercial products of fair size one has single explicit allocation, the other does not have any.
If I was writing for example libraries of custom high performance containers the situation would have been different but still highly localized. And it is sort of very specialized type of development anyways.
It's still useful to teach them in my experience. It's hard to introduce smart pointers without explaining the problem they solve (i.e. wrong or missing uses of delete).
Why would you respond to a comment about a topic you don't understand and spread false information? You clearly cannot tell the difference between garbage collected language and smart pointers.
Smart pointers do not necessarily use reference counting. std::shared_ptr is reference counted, but std::unique_ptr is not. Needless to say that std::unique_ptr should always be the default choice and std::shared_ptr only used when actually needed.
I think you’re making a joke, but reference counting is different than what a unique pointer does. (a destructor is not the same thing as a reference count, even if that reference count is limited as you suggest.)
No, I don't think it's a joke. It's just that when your counter is limited to values of 0 and 1 only, you can optimize it so heavily it almost looks like a different thing entirely: binary semaphores are usually called mutexes, but they're still semaphores.
It was a joke and not a joke, a joke with a kernel of truth.
But I only now just discovered that C23 is genuinely adding `BOOL_MAX`, which reminds me of the classic Fortran —
> The primary purpose of the DATA statement is to give names to constants; instead of referring to pi as 3.141592653589793 at every appearance, the variable PI can be given that value with a DATA statement and used instead of the longer form of the constant. This also simplifies modifying the program, should the value of pi change.
Since that counter can only have two values, it's storage is optimized and merged with the underlying raw pointer itself (not unlike Rust's null pointer optimization for enums): non-null value of the underlying pointer also serve to represent the counter's value of 1, and the null value serves to represent the counter's value of 0. The check to not under-decrement, for example, manifests as the null check before calling the deleter on the underlying pointer.
Sigh, I saw this coming. By this definition, every C++ object with a (non-trivial) destructor would be "reference counted". Sorry, but I am not interested in playing word games.
Nope. Only those with "if (this->inner_resource) { /* delete inner resource */ }" inside the destructor could count, others wouldn't.
Edit: actually, nevermind. You are (almost) right: all objects with automatic storage duration and with non-trivial destructors are, very pedantically speaking, reference counted; but objects with dynamic storage duration are not. So RAII works by leveraging the built-in very primitive and restricted (binary) form of reference counting and builds on top of it to be able to reference-count objects with dynamic storage duration as well.
I can’t upvote this comment enough. The amount of pedantic nonsense on HN these days is disappointing. I’m not sure why I even bother to read comments here anymore.
like the other comment said, std::unique_ptr is not ref counted. Ref counting is one of the ways to implement garbage collection but it is not garbage collection by itself. C++ does not have garbage collection.
C++ does not have garbage collection in the standard library, just as shared_ptr was not part of the standard library in the past. You can currently have optional garbage collection in C++: https://github.com/pebal/sgcl
If you find yourself with the time, and the inclination, give Arrested Development a go. I thought it was fantastic. I think there is a reason that it always sat a little under the radar. You have to actively watch it. It's not suited to being on in the background.
Tobias: You know, Lindsay, as a developer, I have advised... a number of people to explore "modern C++," where everything is RAII, and you never have to write `new` or `delete`.
Lindsay: Well, did it work for those people?
Tobias: No, it never does. I mean, these people somehow delude themselves into thinking it might, but... but it might work for us.
According to the TIOBE index, C++ is the fourth most popular programming language, and has been around for over 35 years, so easily a couple thousand people. The question is how many of them are on HN (probably dozens).
I'll be honest, I didn't get it at first. I thought initially that it was too complex for the teaching example. And then it clicked. You're rather smart aren't you! I guess 24, or 36, or 48 would have worked!
Hey brother! I always love a good quote back. I've occasionally had a 'there are dozens of us' response in the training room or remote chat. Always makes me smile.
I assume you have it on x86_64. I'm trying to make sense of that according to glibc implementation details[1] and Sys V/Itanium ABI.
Default new and delete just use malloc/free.
First 4 ints are interpreted as prev_size and size. prev_size is 0. 33 is 0b10001, size is 32 (bytes, so 8 ints), AMP is 0b001, so not in arena (default sbrk heap, I assume), not mmap'd, prev is used.
I didn't follow how the internal bookkeeping will be updated, but I assume 8 size chunk will be immediately reused on a following `new int[6]`.
Essentially correct. 33 sets up the pointer to appear to glibc as if it were a small, “normal” 32-byte allocation. The default behavior for glibc free() with a small allocation size will be to put it into the thread cache (tcache), which makes it immediately available to be reused by the same thread.
Although you should obviously never write code like this by yourself, understanding weird details like this is very helpful when exploiting memory error bugs in software, as it lets you understand how precisely to subvert the memory allocator to give you access to desired parts of memory.
Non-EV driver here; glad I did a search making the "obvious" reply. Surprisingly, "one pedal driving mode" is a thing. Its described as opt-in with a switch or setting, so I guess there's still a brake pedal. Which means some QA techs must have test plans with "switch off, step on brake pedal" and "switch on, step on brake pedal." Or maybe "switch on, step on brake pedal" is undefined behavior and the compiler can optimize it out.
EVs always have physical brakes and pedal too in addition to regenerative braking. Regenerative braking can't come close to the braking power of disc or drum brakes especially if the battery is full.
Sportier drivers may wish to brake and accelerate simultaneously (rev matching, weight transfer tricks). Normal cars just cut fuel when braking to avoid two-foot drivers burning their brakes.
It's recommended to use virtual destructors for objects that live on the heap. Say you have a base class pointer to an object of a derived class; with nonvirtual destructors the base class determines the destructor that is called, whereas with virtual destructors it's the derived class that chooses the form of the destructor.