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="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.