简体   繁体   中英

General rule of thumb when to return Pointer vs return Object?

In many examples I see code like this:

SomeObject* constructObject() {
    SomeObject* obj = new SomeObject();
    return obj;
}

But what speaks against doing it this way:

SomeObject constructObject() {
    SomeObject obj = SomeObject();
    return obj;
}

?

What is the general rule of thumb of when to return an object vs when to return a pointer?

Edit: A little background:

I am rewriting a renderer that should be fast in both rendering itself aswell as providing the data. The previous programmer stored pointers in a vector. something like: vector<MeshModel*> . MeshModel itself doesnt have any inheritance. In my opinion it would be better to use vector<MeshModel> instead, since I wouldn't jump around randomly in the memory. Is my POV wrong?

std::vector<MeshModel> is more straightforward than std::vector<MeshModel*> .

For use in a std::vector , one might be concerned about the cost of copy/move-construction during vector growth reallocations. If your SomeObject can be moved cheaply, then I would go for the by-value storage. Otherwise, there might be a performance tradeoff during creation of the vector. But that is most likely not worth caring about.

Whether it brings speed while accessing the objects depends on too many other things (everything that affects caching, such as object size, access frequency/stride/predictability, target hardware... too much to list here) - profile if you care about performance. But there's no need to use indirection when you gain nothing from it.

And as pointed out in the comments - stay away from owning raw pointers. std::unique_ptr<MeshModel> would work just fine in the code shown.

Is my POV wrong?

No. Direct values are preferable to indirection whenever the indirection is unnecessary.

So, the question is: Is the indirection needed? We cannot tell that based on the limited context.

PS A function should pretty much never return a bare owning pointer such as in the example. Always use smart pointer for ownership.

Usually the only reason to dynamically allocate an object and return it by-pointer is because you need to use polymorphism (ie you're returning an object that is a subclass of the return-type declared in your function's return-type) and you want to avoid object-slicing . But even then, you should always return using a smart-pointer class (eg std::unique_ptr<BaseClass> or std::shared_ptr<BaseClass> ) instead of returning a raw/C-style pointer, since returning a raw pointer is a recipe for memory leaks.

In older versions of C++ there was a second reason you might want to return an object by-pointer, and that was if the returned object was very large and/or expensive to copy, and your compiler wasn't smart enough to implement Return Value Optimization to avoid requiring an object-copy as part of the return. However, current versions of C++ support move-semantics so that is no longer a concern; returning a "large" object can now be done about as efficiently as returning an object by-pointer.

In my judgment, the change you propose is a "nice to have" which isn't engineering-justified if the application works now. It could in fact be a very, very pervasive change touching most of the code. "Just because you think it stinks" is not a valid engineering reason to change it.

I suggest that you begin by profiling the existing code, after confirming that it does indeed work now, in order to determine conclusively where and why it is right-now "not fast enough" in doing each particular thing that is required of it. You should also profile each of your changed areas to confirm that you did, indeed, obtain the necessary increases in performance. Don't Assume.

Your project-plan should then be strictly driven by the specific areas that the profile results reveal ... and, nothing else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM