Hacker News new | ask | show | jobs
by CyberDildonics 14 days ago
you don't understand what you're talking about Are you insane, You are a weasel Get lost.

Lots of insults, but the difference here is that I know exactly how to do what you're doing in C, but it doesn't seem like you ever tried out modern C++.

How hard is it to understand that to get a class definition, all the stuff that's used inside the class, including declarations of internals like private fields and methods, needs to be included first? How hard is it?

This is a matter of dependencies and if your dependencies are simple definitions too it isn't going to matter. You are going to have to have definitions of your structs and functions in C too. A data structure without dependencies in C++ is no different than a data structure without dependencies in C. This isn't a language issue and has nothing to do with destructors.

without insane C++ classes and features.

It isn't destructors that cause long build times, if it was you could prove it. I said this multiple times but you're mixing a bunch of stuff together because you know staying on topic doesn't match what you're upset about.

I'm talking about systemic problems, which manifest in lots of ways

You didn't give any explanation of these, you just made a lot of claims. You still seem to think claiming something with no explanation is evidence. A kid saying they run fast over and over doesn't prove anything, you have to show it.

You haven't got a clue what you're talking about.

They are both forward declarations which I avoid like the plague for all the reasons I outlined before. Your whole schtick is that you want forward declarations and don't care about all the ownership and value semantics that save you from 50 years of C bugs.

There is no "like every other value" in C++, regardless of how hard people are trying, and regardless of how much complexity these people pile on top of this language.

Another claim without evidence. Make a value, it goes out of scope. Make an 'object' data structure, it goes out of scope. Move it if you need to, so simple!

which you can simply copy as bytes.

Copy constructors do this if you need them to. You can't just use plain structs with static sized arrays for everything, at some point you need to make real data structures that use the heap and then you will need to manage their memory. It could be automated for you but you might have to be a little more open minded.

1 comments

You are continuing to fight strawmans I have never said and continuing to not get what I said and continuing to lecture me about beginner level C++. I am bored.

> Move it if you need to, so simple!

Move it, so simple, pointer invalidation.

Have you thought about... not moving it? So simple! "I need to move the outermost layer of a complicated structure, because I'm too stubborn to have just put this structure on the heap in the first place -- with nodes that link to it, and I'm not sure if other structure point to it... but anyway I NEED to move it, and I'm happy to implement all silly move and copy constructures and conform to this rigid ruleset even though there is no point in 90% of the cases, and that will lead to incredibly hard to diagnose bugs", said... no competent systems programmer ever.

Have you considered why C++ is like a pile on top of a pile of fixes, exceptions, copy semantics, move semantics, rvalue references... That is the polar opposite of simple.

Obviously you have not. But if you want to know, the reason why is that they are trying to treat things as values that are not values but stateful objects. They are trying to make a toolbox of hacks to treat everything the same. It does not work. It is a beginner level cardinal sin.

> at some point you need to make real data structures that use the heap

Do you remember when you were arguing that you want to avoid putting things on the heap because performance, and I said allocating things on the stack is for toy programs, like.. in my last post from 1 hour ago? I think you must have forgotten. Now you're claiming you want to allocate on the heap and I am not doing real datastructures on the heap???

Please give up. It is embarassing.

Or better, please go read any C++ codebase with templates and classes and copy semantics and move semantics. Get more brain damage as a result. And please leave me alone.

Move it, so simple, pointer invalidation.

It works for everyone else, I'm not sure why this is controversial.

You are continuing to fight strawmans

Like bringing up PIMPL for no reason?

Have you thought about... not moving it?

No, because I want to have ownership semantics and be able to return data structures from functions while having clear ownership that is part of the program and not knowledge that has to be gleamed from source code or learning from crashes.

Have you considered why C++ is like a pile on top of a pile of fixes, exceptions, copy semantics, move semantics, rvalue references... That is the polar opposite of simple.

Which one is the argument against destructors? The simplest thing in the world. Copying and moving are solutions to problems you already demonstrated, you just don't want to admit that you and everyone else has them.

Now you're claiming you want to allocate on the heap and I am not doing real datastructures on the heap??? Please give up. It is embarassing.

It's interesting to claim (without evidence) that I don't know what I'm talking about while saying stuff like this. If you follow what I said before the fact is that with your forward declarations you are putting the structs on the heap so that they become globals and can outlive the constructors. Then whatever fields they contain are going to be pointers to the heap for the actual data of the data structure. When you want that data you have to dereference the pointer to the struct, then dereference the pointer to whatever arrays you are using. This is double indirection. It is more allocations, more memory frees, more pointer dereferencing (all of which are slow) and not necessary. In C++ with value semantics that first struct would be on the stack and gets moved or elided out of the function that creates it. You can't do this with forward declaration because you don't know the size yet.

Or better, please go read any C++ codebase with templates and classes and copy semantics and move semantics. Get more brain damage as a result.

How many did you read?

And please leave me alone.

You don't get to fling a bunch of insults then tell someone to leave you alone. I know you want it both ways but that isn't how it works.

>> Move it, so simple, pointer invalidation.

> It works for everyone else, I'm not sure why this is controversial.

Show the evidence. It does not. It introduces vast amounts of complexity. So much that they were thinking they had to extend the syntax. Great, from rule of 3 to 7, from 41 ways to blow your leg off to 118 ways.

I'm betting it means you can easily google LOTS of memory bugs stemming from this complexity. It "just works" for everyone else, until it does not, and then nobody understands what's wrong because they created a complexity monster.

And what do you think how many intended "moves" get silently converted into copies because some failure to properly forward rvalue references and similar?

Show the evidence. It does not. It introduces vast amounts of complexity.

The evidence is that everyone could do what you showed and they don't, they do this instead. In my experience memory ownership bugs are almost non-existent, an entire class of problems is wiped out.

It's clear that since you're asking about this stuff you haven't actually gone down this road yourself, which means that you're railing against something you don't understand out of fear of something different.

  #include <vector>

  using namespace std;

  vector<int> makeVec() {
    vector<int> v{1,2,3};
    return move(v);
  }

  int main() {
    auto  a = makeVec();
    return 0;
  }
Not difficult or complex. In this case you have something that isn't a constructor returning a data structure that contains heap allocation. You don't have to guess at ownership or dig through documentation (if it exists).

Keep an open mind, there's a reason people consider old C style archaic.

I was not asking, and certainly not for a toy example, are you STILL under the impression you need to explain beginner level C++ to me? You can btw remove the move() from the return statement in this example. It's normal to omit it as it is implicit and specifying it does not make a difference. Did I mention that move semantics introduce a ton of complexity and make it non obvious what is happening?

> Keep an open mind, there's a reason people consider old C style archaic.

It is superficially a little bit archaic but it's not as bad or cumbersome as people make it, like baking a good bread from old grains in a modern oven. The point is if you focus on superficialities and micro optimize everything, you will make a mess and get what you deserve (i.e. modern C++).

The result from baking with simple ingredients is better tasting and healthier than a modern factory bread.

What people consider archaic or in particular insufficient is a function of their knowledge and experience. Check out the raddebugger code and the many excellent explanatory videos about the design of the codebase. You will learn a lot and you might change your mind about many of your mainstream positions.

are you STILL under the impression you need to explain beginner level C++ to me?

Yes

you can btw remove the move() from the return statement in this example.

First you say you have a problem with not knowing if something will copy or move, now you have a problem with an explicit move to rely on copy elision.

Seems like you just want to complain about problems that don't exist.

This is why I think it's necessary to explain the basics.

function of their knowledge and experience

Now we are to the "get good" part of the C true believe argument. People have been trying to get good for 50 years and all the same bugs still happen.

You will learn a lot and you might change your mind about many of your mainstream positions.

I've already been on both sides of this argument. I like data structures, value semantics and avoiding double indirection.

Check out the raddebugger code

Check out the code to every other piece of software you use.

> Like bringing up PIMPL for no reason?

What disorder are you suffering from? Please check who was bringing up PIMPL. Hint: it was the person who does not know what they're talking about.

> Which one is the argument against destructors?

oh. my. god. THE COMPLEXITY. The systemic issues.

> Copying and moving are solutions to problems you already demonstrated

Which? I presented my solution to the move problem, it was: just don't move. And for copying: it's very context dependent what "copy" should even mean. There is no point in general in making a single function.

This whole semantics infrastructure is all just there to allow generic template code, which results mostly in: very bad, bloated, and slow code that is full of forgotten edge cases. For example, to take a very popular example, std::sort. you can sort a vector of vectors, it would then use move semantics to swap elements. Fine: I would just sort pointers instead or come up with an ad-hoc solution that is way faster anyway. (other than the fact that general purpose sorting of longer chunks is quite rare in systems programming).

> This is double indirection. It is more allocations, more memory frees, more pointer dereferencing (all of which are slow) and not necessary.

My friend, you don't understand the first thing about how computers perform their work, let alone how you have to balance these concerns with software architectural concerns. You could convert all the std::vectors in your programs and access them using pointers, in most cases you probably wouldn't notice the tiniest bit of a performance difference.

But the reason why C++ likes to embed "objects" as values (even though that's almost invariably bad from an architectural standpoint) is almost entirely unrelated to performance (with the caveat that embedding might save you a couple heap allocs and frees, but for real stateful objects & data structures, that isn't a good reason to embed). Of course you shouldn't add any indirection for objects that aren't really objects but merely a scope-exit, like lock_guard for example.

The primary reason is because it painted itself into that corner. It's syntax & semantics. You wouldn't "profit" from RAII if you added pointer indirection to your objects. (To fix that, later std::unique_ptr<T> was popularized, which again is an embedded struct but contains only a pointer -- which in typical C++ manner introduced its own additional horrors).

Another reason why C++ wants to embed objects is that its operators (like operator[], operator+ etc.) are defined on "value" type syntax expressions. Well it's basically the same reason as above RAII argument, since that argument is about the destructor-"operator". You cannot call methods & operators on pointers. You cannot do `std::vector<Foo> *ptr = ...; do_foo(ptr[i]);`. Get it? The best you could do would be `do_foo(ptr->at(i))` but it's not the same. Part of the reason why C++ calls methods on value type expressions is of course C compatibility, C++ can't afford to mess with pointer syntax and arithmetic.

I'm sorry. C++ is broken.

> How many did you read?

Way too many.

oh. my. god. THE COMPLEXITY. The systemic issues.

I'm hearing it, I'm not seeing it. Repeating the same thing isn't evidence.

My friend, you don't understand the first thing about how computers perform their work, let alone how you have to balance these concerns with software architectural concerns.

Seems like projection when you're fine with double memory allocations and double indirection. Again you can make these bold statements but saying pointer chasing has no performance impact is what people say when they don't understand the cost of TLB misses and caches misses.

C++ likes to embed "objects" as values

"C++" doesn't like to do anything. It has things in the language like destructors that basically no one has ever been against until now.

You wouldn't "profit" from RAII

I don't know what this means but people using features a certain way doesn't have anything to do with destructors. That's the definition of a straw man fallacy.

It's like your C program doing double indirection. You can't blame C for that (unless you want to try to say that not defining your structs is a good idea).

You cannot call methods & operators on pointers. You cannot do `std::vector<Foo> ptr = ...; do_foo(ptr[i]);`. Get it?*

Yes you can, an operator is just a function, get it?. You don't need to because you can use things as values and not fragile pointers that have to have their ownership semantics memorized for every individual data structure and function (interesting that you never addressed this). You don't get operators in C, so it's bold to be wrong and about a feature you are somehow denigrating.

Also one separate function being different than the operator is not a language level feature, it is how that one library data structure is made.

I'm sorry. C++ is broken.

Based on you misunderstanding it because youtubers steered you wrong?

All I was arguing was that destructors are good and you are having a massive reaction to that that seems to include every misguided frustration with the whole language you can think of.

> How many did you read?

Way too many.

And you said it causes brain damage?

> Again you can make these bold statements but saying pointer chasing has no performance impact is what people say when they don't understand the cost of TLB misses and caches misses.

You are right to call this out but I did not mean to imply that it would not increase load on the cache at all. The most important optimization is keeping data structures simple, flat, and coherent. Making many micro optimizations can backfire because it reduces clarity and flexibility. I should not argue that vector metadata block should not be embedded as value in a struct, but move semantics is where it is getting silly, complicated, and we are losing control of program behaviour.

For example, with your cache concerns, don't forget to group data by access patterns and write patterns. Not doing so may hurt the cache more than an indirection. If you blindly embed everything by value religiously, you deserve neither flexibility nor correctness nor performance.

> Yes you can, an operator is just a function, get it?

An operator is just a function but with different syntax. You can not do my example, that snippet does not do the intended job. Get it?

> (unless you want to try to say that not defining your structs is a good idea).

It is a good idea when it's about architecture. It is right to embed small and in particular stateless structs directly, but otherwise adding one level of indirection is often absolutely the right call.

> All I was arguing was that destructors are good

All I'm saying is that destructors, while they may seem convenient, are way overrated and the systemic issues caused by reliance on C++ classes and class features (including destructors) are still not well enough understood by the mainstream in 2026.

If you blindly embed everything by value religiously, you deserve neither flexibility nor correctness nor performance.

I don't know what 'deserve' is supposed to mean, but I just showed how to get all three.

don't forget to group data by access patterns and write patterns

Values on the stack are going to be grouped together and they are going to be in cache.

You realize using two heap allocations means twice the frees, twice the heap contention from multiple threads and chasing through two pointers for every data structure access right? In what universe does this work better than a single pointer lookup?

Making many micro optimizations can backfire

This is an even more handwavey than usual.

All I'm saying is that destructors, while they may seem convenient, are way overrated and the systemic issues caused by reliance on C++ classes and class features (including destructors) are still not well enough understood by the mainstream in 2026.

You can say that but you have given zero evidence of any of this. It took you a very long time to even get to your claim, maybe now you can start to back it up.

Meanwhile I gave extensive evidence based on your own examples of how the same bugs have happened over the last 50 years and double indirection and vague ownership cause problems on small and large levels.

> Also one separate function being different than the operator is not a language level feature, it is how that one library data structure is made.

That's not so much the point: the point is that even when calling a regular method conveniently as ptr->methodname(), you are calling the method name not on a pointer expression but on a value expression. ptr->methodname() is effectively (*ptr).methodname().

That's not so much the point:

It is the point since you compared two things that have different uses, then said you can't call an operator on a pointer, which is wrong.