8

Sometimes I want to delegate the construction of objects that a class owns to a separate function. Something like

Vertex* new_vertex(const Options& options) {
  // do stuff...
  return new Vertex(...);
}

where the function is only intended to be used to within a class that owns the Vertex. Clearly this function can cause some memory-leaking confusion, so I want to make it as clear as possible. Is there a naming convention for such functions?

  • 11
    Yes. // TODO: Fix allocation of raw pointer. – Steven Burnap Jul 15 '15 at 3:18
  • 3
    @StevenBurnap I wouldn't use the word "fix" unless the thing doesn't work. – immibis Jul 15 '15 at 6:15
  • 1
    Just a remark on the concern of "confusion". It is equally important that the caller takes proper care of the returned object. Smart pointers can make this effortless (by making memory management a mechanical habit rather than a continuous exertion of mental effort), but if the caller doesn't have any clear policy or coding standard or notion of hierarchical "object ownership", eventually it will still run into trouble. In some cases, junior programmers might even try to circumvent the unique_ptr by calling its release() function, and use the raw pointers like the old ways. – rwong Jul 15 '15 at 6:28
  • 1
    @StevenBurnap Why not simply // FIXME: Allocation of raw pointer? – Tobias Kienzler Jul 15 '15 at 8:47
  • 1
    Your function makes it pretty clear to me. The return type isn't by value or a reference - either of which would make trying to clear up the memory a non-instinctive syntactic wrangle. The function is called new_vertex so I know the object is newly minted. You could call it Create_new_vertex to be extra clear. As for the idea that you shouldn't manage heap memory without smart pointers, never seen the truth in that - in fact if you can't manage heap memory without them, you've got no business managing heap memory with them either! – Grimm The Opiner Jul 15 '15 at 14:40
21

Return a unique_ptr:

std::unique_ptr<Vertex> new_vertex(const Options& options) {
  // do stuff...
  return std::make_unique<Vertex>(...);
}

There can only ever be one unique_ptr pointing to a given object (unless you abuse it by casting to a Vertex* and back, anyway). You can't ever copy a unique_ptr, only move it. When a unique_ptr is destroyed (and hasn't been moved out of) it even deletes the object for you.

make_unique creates a new Vertex and wraps it in a unique_ptr; the arguments you pass to make_unique are the arguments it passes to the constructor.

  • 4
    This is helpful, but it doesn't really answer my question. I know about smart pointers, I just wanted to know if there's a naming convention for functions that return raw pointers that the user has to take care of. I guess the answer is "no, there isn't, because you should never do that"? – Shep Jul 15 '15 at 7:30
  • 3
    @Shep If you want to indicate to the person calling your function that it creates a new object, unique_ptr does that. If it has to be a name for some reason, then I guess it doesn't, but why does it have to be a name? – immibis Jul 15 '15 at 7:32
  • 8
    @Shep Names are intangible things and everyone is free to ignore them completely. Types on the other hand are enforced by the compiler, which means it requires significant effort to break stuff. Never send a name to do a type's job. – ComicSansMS Jul 15 '15 at 9:05
  • 1
    @Shep there's no harm returning a raw pointer in this case. This case being that you've created an object that it is up to the caller to manage the lifetime of. The caller can always drop it straight into a smart pointer if they think they need to. – Grimm The Opiner Jul 15 '15 at 14:43
  • 1
    @immibis: Why fo you override the template-argument-deduction of std::make_unique? That's unneccessarily verbose and error-prone... – Deduplicator Jul 19 '15 at 1:09
2

Is there a standard way to indicate that a function returns a new pointer?

No, there is no "standard way" (but there is an API design policy currently considered "best practice").

Because of this ambiguity ("what does a function returning a pointer want me to do with it?"), it is currently considered best practice to impose the lifetime and ownership policy, through the return type:

<vertex pointer type> new_vertex(const Options& options);

<vertex pointer type> can be std::unique_ptr ("new_vertex doesn't own the pointer"), or std::shared_ptr ("client code doesn't own the pointer"), or something else, that has clearly defined ownership semantics (for example, Vertex const * const would indicate to client code "read the address and values, but change neither/don't delete the pointer").

Generally, you should not return a raw pointer (but in some cases, "practicality beats purity").

TLDR: there is a best practice (yes), but not a standard way (in the language).

Edit:

where the function is only intended to be used to within a class that owns the Vertex

If the class owns the Vertex, I would write it like this:

class SomeClass // owns the vertex
{
    void do_stuff() // uses the vertex internally
    {
        init_vertex(); // see below
        assert(vertex.get());
        // use vertex as needed
    }
private:
    // "class owns the Vertex"
    std::unique_ptr<Vertex> vertex;

    // sets the internal vertex
    // function doesn't return a pointer of any kind
    void init_vertex(const Options& options); // or "reset_", "refresh_", 
                                              // or "make_" vertex,
                                              // if the pointer can change
                                              // throughout the lifetime
                                              // of a SomeClass instance
};
0

Yes, there are dozens of "standards" about this

XKCD

The answer recommending unique_ptr is probably the best answer, but if you're looking at raw pointers, everyone's developed their own standard.

Generally speaking functions named create_____ or new______ or alloc_____ tend to imply a new object.

However

Consider that you're mixing behaviors. You don't actually care whether this is a new instance of an object or not. What you care about is whether the caller is responsible for destroying the object or not. There are many APIs which hand over the responsibility for an existing object, and those functions will need a matching naming scheme. Perhaps give______.

If you're willing to step a little away from C++...
If you're willing to consider Objective-C to be similar enough to C++ to be a source for an answer, there's actually a real answer in that language. Objective-C manages the lifespan of objects using reference counts. They needed a way to describe whether you were being given responsibility for an object, or merely a reference to an existing object. If you get the answer wrong, you get the ref-counts wrong and lose objects. Accordingly they made a rule: every object you are returned is owned by someone else (so you must increment and decrement the ref count yourself), except for creation calls which pass an already incremented pointer to you (you only have to decrement). These calls were identified by the method name. Methods starting with alloc new copy or mutableCopy always returned a new object. So there, the standard was enforced by the language.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.