C++ isn't a bad langauge

Pages: 12
Its just that there is an endless amount of tiny details you have to learn that can cause your program to catastrophically fail.

Today I learned that:
1
2
myObj x;
x= (myObj) CreateMyObject();

runs not that copy constructor, but the assignment operator. This thing broke my reference counting and it took me 3 hours to find the problem. It was causing SFML to segfault in some other part of the code.
Properly encapsulating can be difficult.

Honestly it really shouldn't matter how many times the copy constructor / assignment operator is called -- your class should be able to handle it.

I would say you probably shouldn't be doing advanced things like reference counting if you don't understand all the tiny details you're talking about. Or rather, you probably shouldn't be doing reference counting at all because it's unnecessarily complicated and doesn't really benefit you very much.
Why would you implement a copy ctor but not an assignment operator?

But I don't see how this is surprising.
I also learned that there's a difference between myObj *x = new myObj; and myObj *x = new myObj(); ... sometimes.

Its just that there is an endless amount of tiny details you have to learn that can cause your program to catastrophically fail.

I think that would be a good enough reason to call it a bad language.

This thing broke my reference counting and it took me 3 hours to find the problem.

Sounds like a job for C++'s built-in garbage collector! Just kidding. You probably count references for something else. Hm do you sometimes feel you focus more on the paint than on the painting?
this is not bad, actually this is what made it a perfect lang,
for starters it's simple
for experts it's powerfull
blueberry wrote:
Its just that there is an endless amount of tiny details you have to learn that can cause your program to catastrophically fail.
No, you just have to keep two things in mind:

1. Initialize your variables (especially pointer)
2. Check your variables for sanity (especially array size/index)

closed account (zb0S216C)
blueberry wrote:
1
2
myObj x;
x= (myObj) CreateMyObject();

"runs not that copy constructor, but the assignment operator."

Not surprisingly. Since x is given a value after its declaration, assignments will be made through the assignment operator, and not the copy or default constructor.

By the looks of it, you're casting the value returned by CreateMyObject( ), and assigning the result to x. If you haven't overloaded your assignment operator, then the compiler will provide a trivial assignment operator.

blueberry wrote:
"This thing broke my reference counting and it took me 3 hours to find the problem. It was causing SFML to segfault in some other part of the code."

I'm going to take a guess here, and say myObj has a pointer inside it? If so, the default assignment operator will copy each member of the left-hand side member-wise. Any pointers within the class will point to the same location. Therefore, deletion of one pointer will affect the other.

Wazzak
Last edited on
The only thing I don't like about C++ itself is that it sometimes feels stitched together and like it doesn't have a set of features so much as a pile of them.

I do like the language now, though. The new features are pretty useful. My favourites are auto and the ability to create std::vectors like this: uses_a_vector({ v1, v2, v3, v4 });.

I think one of the things that puts me off C++ is that it's not very suitable to pure-OOP. C# does OOP better. But in C++, I tend now just to write procedural code and only use objects when I really want or need them. In C# you have to use objects for everything, or else get around it by making static functions and treating classes like namespaces with variables and access modifiers (although in C#, namespaces have access modifiers anyway).
But in C++, I tend now just to write procedural code and only use objects when I really want or need them.
IMO, that's one of C++'s greatest advantages. It doesn't coerce you into using any particular style. After all, not every problem calls for an OOP approach, or a procedural approach.
Yeah, I agree, although like I said you can get around that in languages like C#, which force you into putting everything in a class, by using static functions.
Last edited on
helios wrote:
It doesn't coerce you into using any particular style.


It's to bad purely functional code is a bitch to write in C++, or at the very least ugly as sin :P
I don't see how you could write purely functional code in C++. The language wouldn't work at all without mutable state.
Honestly, I don't think it is. Not in standard C++ at least.
There are some libraries I've seen which try to emulate it, probably by dubiously use of the preprocessor and metaprogramming.
Or rather, you probably shouldn't be doing reference counting at all because it's unnecessarily complicated and doesn't really benefit you very much.


If I had that attitude, I wouldn't have written a single line of code ever.
Btw, I did stick to writing my own classes through and through: I don't use std::vector but my own thing instead, and I am very happy about it.

To give you an example of why it is good to have your own implementation of std::vector:
whenever I try to reference out of bounds, my class will display a stack report within the web browser, with all functions called, and the lines of code and file locations in which the problem occurred.
Everything is neatly formatted in a table, and the files names have links to the svn repository browser on sourceforge.

Saves tons of time.
Last edited on
you probably shouldn't be doing reference counting at all because it's unnecessarily complicated and doesn't really benefit you very much.
I hadn't seen this part.
How can you possibly know that without knowing any details at all about the application?
Saves tons of time.


Saves programmer time. Often, that's the most expensive time, so it's often good to save. Sometimes, the expensive time is execution time, in which case having a container do bounds checking is more expensive than just programming correctly. C and C++ adhere to the principle that you shouldn't have to pay for what you don't use. You choose to use bounds checking, so you choose to pay for it. Others choose not to use it, so they don't pay for it.
Last edited on
@tition,
I don't see why you couldn't do that with std::vector. You'd have to implement the stack unwinding yourself (unless you're using glibc) though.

I use the standard containers because I suspect that the C++ standards committee as well as the teams implementing glibc or clang or Visual C++ (etc.) are better programmers than I am, and know more about optimisation. Also their implementations have existed for some time during which they would have been improved. So, I assume that the standard containers will tend to be faster and more robust than what I would write.
helios wrote:
I hadn't seen this part.
How can you possibly know that without knowing any details at all about the application?


Educated guess. Compilers are very good at optimizing out unnecessary object copies. I've even read articles that suggested passing complex types by value yields better performance than passing them by const reference (though I haven't done my own benchmarks).


It's an optimization thing. As with any optimization, he should be doing benchmark tests to make sure it's actually optimizing and not just needlessly complicating his code.

I would be a little surprised if reference counting objects made a significant difference in performance... but you're right, I don't know the details so I very well could be wrong. The only one who can know if it's worthwhile or not is OP.
Compilers are very good at optimizing out unnecessary object copies.
I've heard similar claims regarding their ability to inline iterators. Yet in my experience, compilers' theoretical cleverness seems to crap out just in your high performance sections, where you need it the most. Either that, or a certain optimization that's available in one compiler isn't available in another, so (in the case of portable code) you end up having to assume the worst case scenario anyway.

Reference counting also lets you implement COW semantics, which no compiler can do, no matter how clever.
Last edited on
Pages: 12