Is there a general rule when to favor a heap object over a stack object if the stack object is passed by value a lot?
-
OK, thanks for the followup. I found an article that has somewhat of a rule about when to favor stack objects. It says that allocating on the heap for 'small objects with value semantics' is a major performance killer:
http://www.jelovic.com/articles/why_java_is_slow.htmThen there are examples of what small objects should NOT be in the heap:
"...? For me these are iterators. I use a lot of them in my designs. Someone else may use complex numbers. A 3D programmer may use a vector or a point class. People dealing with time series data will use a time class. Anybody using these will definitely hate trading a zero-time stack allocation for a constant-time heap allocation. Put that in a loop and that becomes O (n) vs. zero. Add another loop and you get O (n^2) vs. again, zero." -
That comment is not really different from what people here have already told you, right? I mean: iterators are generally not long lived objects, and if you generate a bunch of small value-type objects in a calculation, go ahead and put them on the stack as long as you don't expect them to live after your method finishes. And again: if you really need to, new can be optimized also.
-
Andre. I am seriously considering avoiding the use of 'new' and that's it, whenever right. There are too many fans of 'new' here that don't seem to want to respect that 'new' is first of all dangerous to use, and second a possible performance handicap. Why will java never be faster than C++? It is said in the link above that that has to due with not using the stack.
Most of the comments, other than trying to shoot down, have not supported the question. The question is about passing objects by value and when that is appropriate.
I just read something that says that if the object is 4 bytes or less (like a primitive) then pass by value. However, I guess that would apply too in a recursive function, whereas the test I provided of passing an object of 1000 bytes would not be recommended there.
Again, I am not asking when to prefer a heap object and I don't care about CPU cycles as much as what is faster and what is more bug free.
By the way, I am not afraid of doing something like re-writing the 'new' allocator, but what I am working on is mult-threaded, so I would need the standard multi-threaded allocator. No idea
-
If the size of your object ~ size of pointer - use stack. If the size of your object >> the size of pointer - use heap.
In any case it all depends from your task.
In heap your object has its own life. In stack - only while the control inside the method where it was defined.
Stock usually limited and set during compilation. It usually uses short references that makes it work faster.
Heap could occupy all memory you have. Keep all data in memory, write changes in change log and you will have the best performance. With desktops 8 GB RAM we can afford that.
-
[quote author="Iama Hummingbird" date="1315225821"]Again, I am not asking when to prefer a heap object... [/quote]
This is contradictory to
bq. [thread title] Is there a general rule when to favor a heap object over a stack object if the stack object is passed by value a lot?
[quote author="Iama Hummingbird" date="1315225821"]
and I don't care about CPU cycles as much as what is faster....[/quote]Everyone else here understood your questions so far as if it was of a big concern for you, besides other considerations.
[quote author="Iama Hummingbird" date="1315225821"]Andre. I am seriously considering avoiding the use of 'new' and that's it, whenever right. There are too many fans of 'new' here that don't seem to want to respect that 'new' is first of all dangerous to use[/quote]
Everyone here knows about the dangers of using one tool or the other. You can shoot yourself into the foot with heap allocation as well as with stack allocation. Neither one is more dangerous over the other one. The statement "'new' is first of all dangerous to use" is just plain wrong, in my opinion.
What we want to tell you is that there are no general rule, but at best rules of thumb for those categories of problems. This holds true for almost every questions that arise in the daily live of a software developer. Go on and read the "C++ FAQs":http://www.parashift.com/c++-faq-lite/, for example, you will stumble over that big but all over it.
[quote author="Iama Hummingbird" date="1315225821"]...and second a possible performance handicap.[/quote]
For the vast majority of application developers the speed impact of heap allocation compared to stack is just a plain no-problem. In most cases the bottlenecks caused by other subjects. This is one of the reasons why only few of them care about it. The decision about heap or stack is built upon other criteria, some of them were mentioned earlier.
-
[quote author="Iama Hummingbird" date="1315225821"] The question is about passing objects by value and when that is not appropriate.
[/quote]I have found that parashift.com FAQ site helpful earlier and will get more into it. Basically, I am trying to ask if it would be acceptable in a situation or two. Thanks Volker.
-
[quote author="Iama Hummingbird" date="1315229264"]
I have found that parashift.com FAQ site helpful earlier and will get more into it. Basically, I am trying to ask if it would be acceptable in a situation or two. Thanks Volker.[/quote]We'll be happy to help then. And for an actual problem, maybe with some code snippets, you will most probably get more valuable answers as the usual "it depends..." :-)
-
In that case, please explain these situations ("or two") instead of trying to pry out a general answer. That might foster a more constructive discussion. As Volker explained, people here are not so much fans of new, they just know that it has its merrits. If you find that nobody answered they question you would have liked answered, then perhaps the problem is in a not well articulated question. Please reprase, and make sure the actual question you want to ask is clear and at the top of your message. Further expansions, backgrounds, etc. can come below that. That makes it easier to understand your focus and goals, and thus provide you with answers better suited to those. Note that it was you who started about performance and benchmarks, by the way, not us. So forgive us if we focussed on that aspect a bit too much to your taste.
Then, on what to prefer passing as function parameters:
Personally, I prefer the form that most clearly communicates the purpose of the argument. That is: API design is my primary concern. For value-type parameters, I prefer:- const references or normal values for passing parameters that are only used, but not modified by the method.
- non-const references for parameters that are modified (but try to avoid those, use the return value instead if you can)
- pointers for optional parameters that can be modified (like a second return parameter) and have them be 0 by default. An example is @int QString toInt( bool *ok=0 , intbase=10 ) const@
However, a downside to using references is that when you read the actual function call, there is no visible difference between a reference and a normal by-value call. So, the only way to know if an argument will be modified is to read the declaration of the method that was called (or have a clever enough IDE that shows you such things).
-
BUT:
[quote author="Iama Hummingbird" date="1314914362"] ...
What I would like to try to avoid is having to rip out code [/quote] -
[quote author="Iama Hummingbird" date="1315225821"]... and second a possible performance handicap.
Again, I am not asking when to prefer a heap object and I don't care about CPU cycles as much as what is faster and what is more bug free.[/quote]
If you don't care about CPU cycles, why do you ask for performance? CPU cycles are the counter of performance...
And on the other hand, the bug free stuff: a new needs a delete, that's right. And if people don't use it correctly you have a memory leak, thjat's the possible bug. To avoit that, there are smart pointers.
-
[quote author="Andre" date="1315230832"]That is: API design is my primary concern.[/quote]
This can never be emphasized enough! The first and paramount commandment of software development is create readable, understandable, debugable and maintainable code - even at the cost of performance!
-
It all boils down to a few age old quotes again:
"More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason — including blind stupidity." — W.A. Wulf
"The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet." — Michael A. Jackson
"Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you have proven that's where the bottleneck is." — Rob Pike
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified"[5] — Donald Knuth
"The order in which the operations shall be performed in every particular case is a very interesting and curious question, on which our space does not permit us fully to enter. In almost every computation a great variety of arrangements for the succession of the processes is possible, and various considerations must influence the selection amongst them for the purposes of a Calculating Engine. One essential object is to choose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation." — Ada Byron's notes on the analytical engine 1842.
-
The most sound advice I can give to you, Iama Hummingbird, is to go read code.
There are tons and tons and tons of great open-source projects out there with real-life code for you to look at, including the Qt sources themselves, or KDE (and the list goes on.) If you want to see common practices, pick a good-sized project with a good track record and just open some random .cpp files and their corresponding headers and dig in. The information you glean there will be priceless. Think of it as a do-it-yourself apprenticeship.
Look at how seasoned developers are handling allocation, passing, copying, deletion, and so on. Assume that in a mature enough project, there has been substantial peer review of the code to eliminate a lot of boneheaded coding practices. (They will still be there, at times, though, but they will be the exception rather than the rule.)
If you find concrete examples you are confused about, then a link to the code or a small pasted snippet gives us all a starting point for discussion. At that point, any questions you may have will have a solid foundation for us all to build our conversation on.