LOL, when it's the only one being misused, yes![]()
LOL, when it's the only one being misused, yes![]()
If you mean that C++ is misused by using smartpointers, I fully agree ( const & misses the point of using smartpointers in first place!), One platform (the VM) would have reference tracking for free, when other (native C++), will be an expensive feature, visibly slower than C#/Java.
You can test other claims too, like:
- new in C++ is much slower than new in C# (at least with generational collector, so add sgen to Mono's command line)/Java,
- arrays in C#/Java (which are the closes equivalent with std::vector (as you cannot do pointer arithmetic, and you can also iterate over them) are in general faster than their C++ equivalent (on medium sized programs), because C#/Java have a bound's checking removal algorithms for these structures. You may also try if Java specializes OOP calls (using Polymorphic Inline Caching), making working with OOP a bliss
- just upgrading Mono/JVM you can have faster programs with no change on your side (as Java VM or Mono's VM add optimizations, your applications will get them for free, but static compiled programs would not). You may try Jake2 game engine, and try the equivalent Quake2 demo, and tell me which is faster, as for my machine, Quake2/Java is faster than Quake2
At the end, one very last cool thing Java/.Net world has, and C++ have harder times: to work with multiple (good) languages in parts of project and don't have "Invalid Read Address at 0x0ffaas5dda". I recommend to Kotlin (http://confluence.jetbrains.net/disp...etting+Started) which is Java based but brings some runtime warranties and is really nice to code in.
Reddit-C++ page have a link one week ago, that states the same. And gave numbers how to improve 3x the reference counting, by removing the thread-save code.
The misuse is not using smart pointers in the first place, but not passing them as const reference on the function call. Because if the function called is only using the pointer for the duration of its life time, not taking ownership by storing a copy of the pointer at some global level why increment the usage counter? Lets say your function actually does store it for later reference, then the code would look like this:
This code will work as the assignment operator for shared_ptr (both the C++11 version and the boost version) take a const reference as parameter. So passing the smart pointer as value instead of reference is a misuse, especially because it can be passed around for many times before some function actually stores it for later use (or maybe it won't be stored at all).Code:void ProcessItem(const std::shared_ptr<Item> &item) { someOtherSmartPointer = item; }
That depends a lot on the malloc implementation wrapped around by C++ new. And also the average C#/Java program will do a lot more dynamic memory allocations then a C++ one because in C++ it's possible to place a temporary instance of a class on the stack, with C#/Java you can only store on the stack primitive types, any class has to be dynamically allocated.
But an array in C#/Java can not be resized, and the main reason for using C++ std::vector is it's ability to resize at runtime, so they are not at all equivalent
True, with C++ you only benefit from optimizations in the standard library without rebuilding the program, so it's a good reason for the big bad corporations that only release binary blobs, but you're talking to a Gentoo user here who is not scared of an `emerge -e world` after upgrading the toolchain
I am not familiar with Jake2, so I can only speculate on the possible reasons for that, ranging from Jake2 taking advantage of some newer features that were not available 15 years ago when the original Quake2 was written (like multithreading or maybe even newer OpenGL features) to some incompatibilities of Quake2 with newer OS versions, for example Diablo 2 runs like crap on Windows Vista or newer and it's only 12 years old.
So Kotlin tries to bring in features from C# and C++ while maintaining compatibility with JVM?
Well, their code is bogus, they increment/decrement the pointer to the counter, not the value itself. And you can only use their hack when you know multiple threads will never share a pointer, it's a lot better to make sure you only make a copy of the smart pointer when actually required to. In a multi threaded application there should be limited number of functions that are invoked on a different thread, and those function would take the smart pointer as value, while the rest of the functions as const reference.
If you use const & instead of raw pointer is really the same, and it miss the point of shared_ptr. This is why I told that is miss the point of shared pointer. Also having to enable a feature with performance implications means, so you use just minimally, means that users have to get extra thought if they want to use a feature or not, and they may not use it. And in Java you may get the performance right, and having the feature, when in C++ you may not have it, either the feature or the performance.
I'm talking about default implementation/featureset. And if you use the same parameter for Java about Escape Analysis, it will convert heap allocations as stack allocations (as long the JIT can prove them safe). C# have "struct" keyword that put data on a stack, so there is nothing to complain on C# too.
Yet, they are not equivalent for other reasons too: arrays are allocated always on heap on VM languages too, but are closer equivalents than the Generic collections (at least on Java, as you noticed it, but also in C#, as the iteration will do every time a virtual call, as collections have to implement IEnumerable<T>)
I think about the most users, they update the runtime when they update the OS/distribution. It seem to me you're not a Gentoo emerge guy, but even you would be one, I can say to you that Java was many times on the top of fast code, before GCC would catch up.
Jake2 is not faster as of OpenGL rewrite, but it would make sense even it would happen for this reason, but also because Java code can be sometimes optimized more today that a lot of C pointers code may be.
It brings (maybe) some features of C#, but most likely the source was Scala and other JVM languages, but I did not see any C++, the single reference in their FAQ page is:
Consider, for instance, the chaos that existed in C++ with the wide variety of different 'custom' types created to hold booleans before the language designers finally added a standard 'bool' type to the language in an attempt to control the chaos.
Source
:
This would crash! I'm not saying that in places where you "obviously know" that the shared pointer cannot be null, to not use the const& construct, but you are basically on your own when you work with const references! So be aware, and use the principle: "the root of all evil is premature optimization".Code:std::shared_ptr<std::string> previous_message; void send_message(const std::shared_ptr<std::string> &msg) { previous_message = 0; std::cout << *msg << std::endl; previous_message = msg; } (...) send_message(std::shared_ptr<std::string>(new std::string("Hi"))); send_message(previous_message);
Not at all, the const reference to a shared_ptr is all you need in order to increment the usage count of the existing shared_ptr. While having only a raw pointer you could only create a shared_ptr with a distinct counter and the original shared_ptr would free the pointer making your band new shared_ptr hold a dangling pointer.
I was hoping for a crash, but I wasn't so luckyCode:#include <memory> #include <iostream> std::shared_ptr<int> x; std::shared_ptr<int> y; void updatex(const std::shared_ptr<int> &newX) { x = newX; } void updatey(int *newY) { y = std::shared_ptr<int>(newY); } int main() { { std::shared_ptr<int> tmpx(new int(1)); std::shared_ptr<int> tmpy(new int(2)); updatex(tmpx); updatey(tmpy.get()); std::cout << "tmpx=" << *tmpx << std::endl; std::cout << "tmpy=" << *tmpy << std::endl; } std::cout << "x=" << *x << std::endl; std::cout << "y=" << *y << std::endl; return 0; }But running it with valgrind I got:
So not only y holds a dangling pointer that might point to a random value, but it will also try to free the pointer a second time! While x correctly took over ownership from tmpx.Code:tmp=1 tmp2=2 x=1 ==32677== Invalid read of size 4 ==32677== at 0x401215: main (in /home/andrei/Projects/smart_pointers/a.out) ==32677== Address 0x59790f0 is 0 bytes inside a block of size 4 free'd ==32677== at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387) ==32677== by 0x401330: main (in /home/andrei/Projects/smart_pointers/a.out) ==32677== y=2 ==32677== Invalid free() / delete / delete[] ==32677== at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387) ==32677== by 0x401578: std::shared_ptr<int>::~shared_ptr() (in /home/andrei/Projects/smart_pointers/a.out) ==32677== by 0x560D870: exit (in /lib64/libc-2.13.so) ==32677== by 0x55F50A3: (below main) (in /lib64/libc-2.13.so) ==32677== Address 0x59790f0 is 0 bytes inside a block of size 4 free'd ==32677== at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387) ==32677== by 0x401330: main (in /home/andrei/Projects/smart_pointers/a.out)
I probably think in "proprietary world" (Windows/MacOS X) terms, where you have lots of 3rdParty apps installed that will not be updated together with the OS. But for a regular Linux distribution an OS update would also bring all the apps rebuilt with the new toolchain.
Again, if your comparing a C binary from 15 years ago with a Java program running on a recent version of JRE, Java will have an advantage. As you said above, the Java program will take advantage of the new JVM while the C blob is forever stuck in 1997. And I'm sure the Java code being more recent also helps, I doubt if Jake2 was written in 1997 (using JDK 1.0 or 1.1 whatever was the current version at that time!!!), it would perform the same.
It might be a feature of Scala, I don't think i even heard of that language before, but it's also in C++... "Operator overloading" on this page http://confluence.jetbrains.net/disp...arison+to+Java
You misunderstood the problem,
The problem is when you have side effects, and try this:
I cannot compile on Gcc now, may you try to reproduce if you have a crash? (I think that you should, and I'm not talking about dangling pointers, which is fun to have in your applicationCode:#include <memory> #include <iostream> std::shared_ptr<int> x; void resetX() { x = std::shared_ptr<int> (0); } void updatex(const std::shared_ptr<int> &newX) { resetX(); //code have side effects that do set the //reference count of X to zero //the referene to newX is wrong std::cout << "x=" << newX << std::endl; } void updatex_safe_and_slow(std::shared_ptr<int> newX) { resetX(); //code have side effects that do set the //reference count of X to zero, but you have still a safe copy std::cout << "x=" << newX << std::endl; } void main() { { x =std::shared_ptr<int> (new int(1)); updatex_safe_and_slow(x); } { x =std::shared_ptr<int> (new int(1)); updatex(x); } })