5 ms·
Guilty. Of writing C++ as if it were C. Sometimes even with classes. Yes, I use memcpy instead of copy constructors. I find "modern C++" horrible to read. Indi
by ratboy666 11y ago
Guilty. Of writing C++ as if it were C. Sometimes even with classes. Yes, I use memcpy instead of copy constructors. I find "modern C++" horrible to read. Indication of object lifetime? Ownership?
Um... why? If the development support does not include a garbage collector, I have to be very careful about these things. And, I am. Very careful indeed. I just use the approach I do in C, and assume NOTHING from C++. Honestly, I do NOT assume that the language system, compiler or run-time can do it properly. I have been bitten too many times.
I do presume a garbage collector at the very next level up.
Yes, you may find my code "horrible to read". And, yes, I have gone into profane rages over C++ code. It happens when the code bullies me -- with hopeless error messages for simple typos. When simple changes cause the application to no longer link. When simple changes cause massive explosions in object size. In fact C++ is so complex, it encourages cargo cult programming. Not just use of libraries, but enforced cargo-cult when USING the libraries. Because, raisons.
Not just a language -- hell-spawn. Sorry, "modern hell-spawn".
- 72deluxe 11y agoThe problem is that if you were hit by a bus, the next guy maintaining the code has to know about where everything is cleaned up and has to know all of the secrets that you know and that you decided you knew better than the compiler in areas. This makes for unmaintainable code. Ownership is very important because if you don't know who owns it, who will clean it up?? If you don't know how long an object will be around because you've got a pointer, it is now a dangling pointer and attempts to use it will cause chaos. So object lifetime is important too. The error messages are usually quite helpful. clang's messages are more helpful for gcc, I have found. C++ is complex, but you can still write safe code without using any of the complexities.
- vvanders 11y agoIf you hate the idea of ownership and lifetimes I want to stay the hell away from any codebase you work on.
- ratboy666 11y agoNo, what I "hate" is the idea that C++ promotes "automatic" management of "ownership and lifetime" without a garbage collector. Which works, except when it doesn't. Which results in stuff like reference counting in the codebase. Which, of course, changes on a whim. Example: the CEF3 library (chromium embedded framework). Reference counted objects. Which requires source code changes depending on the version of CEF 3 being used. Requires VERY deep analysis to determine what to change in the using code. Really -- because the objects participate in a multi-threaded library. So, most code ends up as "cargo cult". Since my code doesn't fit into the CEF3 object model, I do the contortions needed -- building another layer.
- vvanders 11y agoOwnership and Lifetimes != Reference counting. Reference counting is code smell that you don't have a clear ownership model. Take a look a Rust for something more along the lines of what I'm talking about. There's been quite a few people who've re-written their C/C++ code to Rust only to find out that they didn't have a clear ownership model and found architectural improvements because of it.
- 72deluxe 11y agoRAII solves this. Allocate all you need in the constructor, tidy up in the destructor. So when the parent item gets cleaned up, the child items get cleaned up too (so lifetime is sorted for you, and ownership is done too as the parent that owns it is getting cleaned up). You will eventually only have one parent item but if you tidy everything up for that in its destructor, the lifetimes of everything is sorted. If your acquisition of a resource fails or initialisation fails, throw an exception in the constructor. C++11's threading support library in the STL should help your threaded problems. If you need containers of items, put them into an STL container. Don't allocate them with new - write a move constructor for your item and it'll be moved. Or a copy constructor; follow the "rule of 5" if you have pointer-held items in your object (probably best not to), or "rule of 0" and let the compiler do it for you. std::move your items into the container. Use const references if you want to let something else use it, ordinary references if you want them to modify it. Or if you must use naked pointers, put them in a unique_ptr so it gets cleaned up eventually (http://en.cppreference.com/w/cpp/memory/unique_ptr http://en.cppreference.com/w/cpp/memory/unique_ptr). Or shared_ptr in other areas (see Stroutrup 5.2.1 in C++ 4th edition). If you need naked pointers, allocate them on the heap but wrap them in std::unique_ptr or have a vector of unique_ptr. If your objects are child items in a class hierarchy (e.g.. ChildClass : public BassClass) or the base class is an abstract class and you want to have a generic STL container (like std::vector<BaseClass* >) to store all base and child items in one neat place, you will have to use pointers (as you can't have std::vector<MyAbstractBaseClass> but you can have std::vector<MyAbstractBaseClass* >), you will need to take care in the containing object's destructor to clean up this container, eg. while(!vector.empty()) { delete vector.back(); vector.pop_back(); } You shouldn't need reference counting. A read of Stroustrup's C++ Fourth Edition book and the "tour of C++" section toward the beginning will help you immensely.
- scott_s 11y agoIf you don't want to use basic C++ features such as copy constructors, then why use C++ and not C?