Is this the right way to return a struct in a parameter? - c++

I made the following method in a C++/CLI project:
void GetSessionData(CDROM_TOC_SESSION_DATA& data)
{
auto state = CDROM_TOC_SESSION_DATA{};
// ...
data = state;
}
Then I use it like this in another method:
CDROM_TOC_SESSION_DATA data;
GetSessionData(data);
// do something with data
It does work, returned data is not garbage, however there's something I don't understand.
Question:
C++ is supposed to clean up state when it has exitted its scope, so data is a copy of state, correct ?
And in what exactly it is different from the following you see on many examples:
CDROM_TOC_SESSION_DATA data;
GetSessionData(&data); // signature should be GetSession(CDROM_TOC_SESSION_DATA *data)
Which one makes more sense to use or is the right way ?
Reference:
CDROM_TOC_SESSION_DATA

Using a reference vs a pointer for an out parameter is really more of a matter of style. Both function equally well, but some people feel that the explicit & when calling a function makes it more clear that the function may modify the parameter it was passed.
i.e.
doAThing(someObject);
// It's not clear that doAThing accepts a reference and
// therefore may modify someObject
vs
doAThing(&someObject);
// It's clear that doAThing accepts a pointer and it's
// therefore possible for it to modify someOjbect
Note that 99% of the time the correct way to return a class/struct type is to just return it. i.e.:
MyType getObject()
{
MyType object{};
// ...
return object;
}
Called as
auto obj = getObject();
In the specific case of CDROM_TOC_SESSION_DATA it likely makes sense to use an out parameter, since the class contains a flexible array member. That means that the parameter is almost certainly a reference/pointer to the beginning of some memory buffer that's larger than sizeof(CDROM_TOC_SESSION_DATA), and so must be handled in a somewhat peculiar way.

C++ is supposed to clean up state when it has exitted its scope, so
data is a copy of state, correct ?
In the first example, the statement
data = state
presumably copies the value of state into local variable data, which is a reference to the same object that is identified by data in the caller's scope (because those are the chosen names -- they don't have to match). I say "presumably" because in principle, an overridden assignment operator could do something else entirely. In any library you would actually want to use, you can assume that the assignment operator does something sensible, but it may be important to know the details, so you should check.
The lifetimes of local variables data and state end when the method exits. They will be cleaned up at that point, and no attempt may be made to access them thereafter. None of that affects the caller's data object.
And in what exactly it is different from the following you see on many
examples:
CDROM_TOC_SESSION_DATA data;
GetSessionData(&data);
Not much. Here the caller passes a pointer instead of a reference. GetSessionData must be declared appropriately for that, and its implementation must explicitly dereference the pointer to access the caller's data object, but the general idea is the same for most intents and purposes. Pointer and reference are similar mechanisms for indirect access.
Which one makes more sense to use or is the right way ?
It depends. Passing a reference is generally a bit more idiomatic in C++, and it has the advantage that the method does not have to worry about receiving a null or invalid pointer. On the other hand, passing a pointer is necessary if the function has C linkage, or if you need to accommodate the possibility of receiving a null pointer.

Related

how to make sure that a function won't get a garbage pointer?

I have a function that accepts a pointer and return an enum depending on some conditions related to that pointer:
my_enum function(char* prt)
{
/* function body*/
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
I have another function which also accepts a pointer, invokes my_function and reacts to the obtained value:
void another_function(char* ptr)
{
my_enum result = function(ptr);
if (result == MY_VALUE) std::cout<<"OK"<<endl;
}
I'm running Valgrind to check for memory leaks. The above code results in the following error:
Conditional jump depends on an uninitialized variable.
In fact, it is possible to pass an uninitialized pointer to the function function.
My question is: What is the best way of dealing with this situation (apart from using references instead)? I can't make sure that everyone who will use that code, will initialize the pointer that he will pass to the function. I can't check inside my function if the pointer points to some garbage (I'm checking whether it is a null pointer though) as well.
Should I ignore such errors? If they are useless, why does Valgrind bother to inform me about them? There must be something I can do.
How far are you willing to go? If someone WANTS to break your code, they will, you can't help it.
The more efficient protections you apply the more difficult they get.
The one simple one is to check for NULL. That doesn't prevent stupid pointers, but it prevents ones consciously invalidated. Most people are satisfied by that.
Then you may give the pointer a wrapper class. Instantiating this class requires a valid object pointed to (or some hopeless jumping through hoops to give it an invalid one, which amounts to purposefully shooting your foot), so no scenario of uninitialized pointer can occur - but the object can cease to exist before its pointer is used.
Then you can maintain a factory/manager class for these objects and their pointers. Every time the pointer destination object is created or destroyed, its pointer is created or invalidated. This will be fail-proof unless your code is multi-threading and destruction can occur while your function is already past the checks and before using the validated value.
Then you can add thread safety, wrapping both your function and the manager in mutexes. This adds all kinds of headaches related to deadlocks and synchronization. But the user must really try very hard to create a class derived from yours (probably with #define private public first) that overrides its safety features...
With each step your overhead climbs to levels where the effect really stops being worth the effort. So just check that pointer for NULL and stop worrying about others out to get you.
Opinions will vary on what is the "best" approach, since it is impossible to prevent someone passing a bad (e.g. uninitialised, dangling) pointer at all.
A common solution is to avoid raw pointers altogether, and write the function in a way that does not accept a pointer at all.
One way is to accept a reference. Writing your code so it doesn't use raw pointers at all makes it harder to call your function with a bad parameter. The limitation is that the caller can still create a bad reference (e.g. by dereferencing a bad pointer) but it takes more effort (or a longer sequence of mistakes if done unwittingly) to pass a bad reference to a function than it does to pass a bad pointer.
Another way is to accept some class object by value (or reference, in some cases) to hold your pointer. Then implement all member functions of that so that they prevent a situation of holding a bad pointer. Give that class no member functions that accept a pointer. Ensure the constructors and other member functions maintain consistency (formally, the constructors establish a rigorous set of invariants, other member functions maintain that set of invariants). This includes techniques like throwing an exception if an attempt is made to construct an object using bad data (if an exception is thrown in the process of constructing an object, that object never exists, and cannot be passed in any manner to your function). As a result, your function can assume - if it is successfully called - that the data it receives is valid.
The thing is, the above make it harder to accidentally pass bad data to your function. No technique can absolutely prevent someone who is determined enough (whether through genius or foolishness) to find a way to bypass all the safeguards, and to pass bad data to your function.
There are essentially two solutions.
Expect a valid pointer and state that clearly in the documentation of your API. Then any invalid use will cause UB, but it's not your fault. However, handling raw pointers is C-style and frowned upon by C++ programmers.
Take (the reference to) an encapsulated pointer type, which is always sensibly initialised, such as std::string (instead of const char*), std::unique_ptr, or std::shared_ptr. For example,
my_enum function(std::string const&str)
{
/* function body*/
if (str.empty()) // deal with improper input
std::cerr<<"warning: empty string in function()"<<std::endl;
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
or
my_enum function(std::unique_ptr<SomeType> const&ptr)
{
/* function body*/
if (!ptr) { // deal with improper input
std::cerr<<"warning: invalid pointer in function()"<<std::endl;
return enum_error;
}
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
This avoids raw pointers and is the C++ way for dealing with this sort of situation. One problem with the latter code is that it only works for unique_ptr arguments. One may generalise this to be overloaded (using SFINAE or otherwise) to take (const reference to) any auto-pointer like objects (for instance defined as objects obj with member obj::get() const returning a const obj::element_type*).

Should I avoid implicit behavior by passing a redundant parameter?

I'm developing a class that, among other things, will create a block of memory and perform some processing on this memory. The user will do something like this:
MyClass m;
float* data = m.createData();
/* user writes to `data` ... */
m.processData();
Keep in mind that createData() will be called only once, MyClass keeps an internal pointer to data, and all processData() calls will always act on this data.
My question is about the signature of the processData() method. I'm a bit uncomfortable with the fact that processData() implicitly modifies data. Should I require data to be passed as a parameter (even being redundant) just to make this behavior explicit to the user?
MyClass m;
float* data = m.createData();
/* user writes to `data` ... */
m.processData(data);
I'm a bit uncomfortable with the fact that processData() implicitly modifies data.
Actually, processData doesn't modify data at all. Given your description, it modifies the object that data points to. But only because the internal pointer happens to point to the same object.
Should I require data to be passed as a parameter (even being redundant) just to make this behavior explicit to the user?
If you intend to use the internal pointer anyway, then definitely not. Requiring user to pass an argument that's not used would be very confusing.
If you intend to use the passed pointer instead, then it would not make much sense to store the pointer within the class.
user needs to access this data (write and read).
The object oriented approach is to not return the pointer to the data, but instead write member functions to MyClass that perform the writing and reading.
A non-object-oriented approach is fine as well: Replace createData and processData with free functions, return a std::unque_ptr<float[]> (or better yet, use std::vector) to the data, and get rid of MyClass entirely.
No, you should not.
Your function createData() returns a pointer. This implies, that the data to which the pointer points might be modified.
If you want to pass a copy of your data to the user, don't pass a pointer (but it sounds like you don`t want that).
processData() is a member function of your MyClass - as long as it is not marked const you don't give any guarantees that you don't modify the internal data.
The only point where i would watch out is, if you want to invalidate the pointer you passed to the user. Then you should explicitly tell about this in your documentation or even switch to some kind of smart pointer.
If this approach seems to unsafe for you, it might be a better way to not return a pointer, but instead provide member functions to do the read/write access. This gives you full control about how and when the user changes your data, e.g. for thread-safety.

Can `*this` be `move()`d?

I would like to define a class for marshalling data; when marshalling is finished, I would like to move the marshalled data out from within it, which will probably invalidate the marshalling object.
I believe this is possible with the static function extractData below:
class Marshaller
{
public:
static DataType extractData(Marshaller&& marshaller)
{
return std::move(marshaller.data);
}
private:
DataType data;
}
This is a bit inconvenient to call, though:
Marshaller marshaller;
// ... do some marshalling...
DataType marshalled_data{Marshaller::extractData(std::move(marshaller))};
So can I wrap it with a member function?
DataType Marshaller::toDataType()
{
return Marshaller::extractData(std::move(*this));
}
This would, of course, be called using:
DataType marshalled_data{marshaller.toDataType()};
...which, to me, looks much nicer. But that std::move(*this) thing looks awfully suspicious. In the context of the call to toDataType(), marshaller can't be used again, but I don't think the compiler can know that: the body of the function could be outside the caller's compilation unit, so there's nothing to indicate that marshaller has had move() applied to it.
Is this undefined behavior? Is it perfectly fine? Or somewhere in between? Is there a nicer way to accomplish the same goal, preferably without using a macro or requiring the caller to explicitly move marshaller?
EDIT: With both G++ and Clang++, I found that not only could I compile the above use case, but I could actually continue to make modifications to the underlying data via the marshaller, then re-extract the modified data using the toDataType function. I also found that the already-extracted data in marshalled_data continued to be changed by marshaller, which indicates that the marshalled_data is shared between the marshaller and the calling context, so I suspect that there is either a memory-leak or undefined behavior (from double-deletion) here.
EDIT 2: If I put a print statement in DataType's destructor, it appears twice when the caller leaves scope. If I include a data member in DataType that has an array in it, with a corresponding new[] and delete[], I get a glibc "double free or corruption" error. So I'm not sure how this could be safe, even though several answers have said that it's technically allowed. A complete answer should explain what is required to use this technique correctly with a non-trivial DataType class.
EDIT 3: This is enough of a rabbit-hole/can-of-worms that I've opened up another question to address my remaining concerns.
According to the standard the move-from object will still be valid although its state is not guaranteed, so it seems that moving from *this would be perfectly valid. Whether it's confusing to users of your code is another question entirely.
All that said it sounds like your real intention is to link the destruction of the marshallar with the extraction of the data. Did you consider doing all the marshalling within a single expression and letting a temporary take care of things for you?
class Marshaller
{
public:
Marshaller& operator()(input_data data) { marshall(data); return *this; }
DataType operator()() { return std::move(data_); }
private:
DataType data_;
}
DataType my_result = Marshaller()(data1)(data2)(data3)();
I would avoid moving from *this, but if you do it, at least you should add rvalue ref-qualifier to the function:
DataType Marshaller::toDataType() &&
{
return Marshaller::extractData(std::move(*this));
}
This way, the user will have to call it like this:
// explicit move, so the user is aware that the marshaller is no longer usable
Marshaller marshaller;
DataType marshalled_data{std::move(marshaller).toDataType()};
// or it can be called for a temporary marshaller returned from some function
Marshaller getMarshaller() {...}
DataType marshalled_data{getMarshaller().toDataType()};
There is nothing inherently unsafe about calling move(*this). The move is essentially just a hint to a function being called that it may steal the internals of the object. In the type system, this promise is expressed through && references.
This is not related to destruction in any way. The move does not perform any type of destruction - as mentioned, it just enables us to call functions taking && parameters. The function receiving the moved object (extractData in this case) also does not do any destruction. In fact, it needs to leave the object in a "valid but unspecified state". Essentially, this means that it must be possible to destroy the object in the normal way (by delete or by going out of scope, depending on how it was created).
So - provided your extractData does what it should and leaves the object in a state that allows it to be destructed later - there is nothing undefined or dangerous going on with respect to the compiler. There could of course be a problem with users of the code being confused, since it is not entirely obvious that the object is being moved from (and likely won't contain any data later). This could perhaps be made a little clearer by changing the function name. Or (as another answer suggested) by &&-qualifying the entire method.
I think you shouldn't move from *this, but from its data field. Since this clearly will leave the Marshaller object in an valid but unusable state, the member function that does this should itself should have an rvalue reference qualifier on its implicit *this argument.
class Marshaller
{
public:
...
DataType Marshaller::unwrap() && { return std::move(data); }
...
private:
DataType data;
};
Call it, if m is Marshaller variable, as std::move(m).unwrap(). There is not need for any static member to accomplish this.
You write that you'd like to simultaneously destroy the Marshaller and remove the data from it. I really wouldn't worry about trying to do these things simultaneously, just move the data out first and then destroy the Marshaller object. There are a number of ways to get rid of the Marshaller without thinking much about it, perhaps a smart pointer makes sense for you?
One option for refactoring this would be to give DataType a constructor that takes a Marshaller and moves the data out (the 'friend' keyword will allow you to do this since the DataType will then be able to reach that private 'data' variable).
//add this line to the Marshaller
friend class DataType;
struct DataType
{
DataType(Marshaller& marshaller) {
buffer = marshaller.data.buffer;
}
private:
Type_of_buffer buffer;//buffer still needs to know how to have data moved into it
}
You could also give it an assignment operator that does that same (I think this will just work:
DataType& operator=(Marshaller&& marshaller) {
this.buffer = std::move(marshaller.data.buffer);
return *this;
}
)
I would avoid using move on *this, just because it's going to throw people off even if it is right. It also seems like stack based buffer containers might get you into trouble.
You seem to be concerned with the Marshaller being called again outside the compilation unit. If you have intense parallel code and are playing fast and loose with the marshaller, or you are copying pointers to your marshaller willy-nilly then I think your worries are justified. Otherwise, look at how the Marshaller is being moved around and make sure you've structured your code for good object lifetime (use object references whenever you can). You can also just add a member flag to marshaller that says whether 'data' has been moved and throw an error if someone tries to access it after it's left (if you're parallel be sure to lock). I would only do this as a last resort or quick fix since it doesn't seem right and your co-devs will wonder what's up.
I have some nits to pick if you have a moment:
your extractData method is missing the static keyword
you mix brackets and parenthesis on your DataType declartion line

How to pass std::unique_ptr around?

I am having my first attempt at using C++11 unique_ptr; I am replacing a polymorphic raw pointer inside a project of mine, which is owned by one class, but passed around quite frequently.
I used to have functions like:
bool func(BaseClass* ptr, int other_arg) {
bool val;
// plain ordinary function that does something...
return val;
}
But I soon realized that I wouldn't be able to switch to:
bool func(std::unique_ptr<BaseClass> ptr, int other_arg);
Because the caller would have to handle the pointer ownership to the function, what I don't want to. So, what is the best solution to my problem?
I though of passing the pointer as reference, like this:
bool func(const std::unique_ptr<BaseClass>& ptr, int other_arg);
But I feel very uncomfortable in doing so, firstly because it seems non instinctive to pass something already typed as _ptr as reference, what would be a reference of a reference. Secondly because the function signature gets even bigger. Thirdly, because in the generated code, it would be necessary two consecutive pointer indirections to reach my variable.
If you want the function to use the pointee, pass a reference to it. There's no reason to tie the function to work only with some kind of smart pointer:
bool func(BaseClass& base, int other_arg);
And at the call site use operator*:
func(*some_unique_ptr, 42);
Alternatively, if the base argument is allowed to be null, keep the signature as is, and use the get() member function:
bool func(BaseClass* base, int other_arg);
func(some_unique_ptr.get(), 42);
The advantage of using std::unique_ptr<T> (aside from not having to remember to call delete or delete[] explicitly) is that it guarantees that a pointer is either nullptr or it points to a valid instance of the (base) object. I will come back to this after I answer your question, but the first message is DO use smart pointers to manage the lifetime of dynamically allocated objects.
Now, your problem is actually how to use this with your old code.
My suggestion is that if you don't want to transfer or share ownership, you should always pass references to the object. Declare your function like this (with or without const qualifiers, as needed):
bool func(BaseClass& ref, int other_arg) { ... }
Then the caller, which has a std::shared_ptr<BaseClass> ptr will either handle the nullptr case or it will ask bool func(...) to compute the result:
if (ptr) {
result = func(*ptr, some_int);
} else {
/* the object was, for some reason, either not created or destroyed */
}
This means that any caller has to promise that the reference is valid and that it will continue to be valid throughout the execution of the function body.
Here is the reason why I strongly believe you should not pass raw pointers or references to smart pointers.
A raw pointer is only a memory address. Can have one of (at least) 4 meanings:
The address of a block of memory where your desired object is located. (the good)
The address 0x0 which you can be certain is not dereferencable and might have the semantics of "nothing" or "no object". (the bad)
The address of a block of memory which is outside of the addressable space of your process (dereferencing it will hopefully cause your program to crash). (the ugly)
The address of a block of memory which can be dereferenced but which doesn't contain what you expect. Maybe the pointer was accidentally modified and now it points to another writable address (of a completely other variable within your process). Writing to this memory location will cause lots of fun to happen, at times, during the execution, because the OS will not complain as long as you are allowed to write there. (Zoinks!)
Correctly using smart pointers alleviates the rather scary cases 3 and 4, which are usually not detectable at compile time and which you generally only experience at runtime when your program crashes or does unexpected things.
Passing smart pointers as arguments has two disadvantages: you cannot change the const-ness of the pointed object without making a copy (which adds overhead for shared_ptr and is not possible for unique_ptr), and you are still left with the second (nullptr) meaning.
I marked the second case as (the bad) from a design perspective. This is a more subtle argument about responsibility.
Imagine what it means when a function receives a nullptr as its parameter. It first has to decide what to do with it: use a "magical" value in place of the missing object? change behavior completely and compute something else (which doesn't require the object)? panic and throw an exception? Moreover, what happens when the function takes 2, or 3 or even more arguments by raw pointer? It has to check each of them and adapt its behavior accordingly. This adds a whole new level on top of input validation for no real reason.
The caller should be the one with enough contextual information to make these decisions, or, in other words, the bad is less frightening the more you know. The function, on the other hand, should just take the caller's promise that the memory it is pointed to is safe to work with as intended. (References are still memory addresses, but conceptually represent a promise of validity.)
I agree with Martinho, but I think it is important to point out the ownership semantics of a pass-by-reference. I think the correct solution is to use a simple pass-by-reference here:
bool func(BaseClass& base, int other_arg);
The commonly accepted meaning of a pass-by-reference in C++ is like as if the caller of the function tells the function "here, you can borrow this object, use it, and modify it (if not const), but only for the duration of the function body." This is, in no way, in conflict with the ownership rules of the unique_ptr because the object is merely being borrowed for a short period of time, there is no actual ownership transfer happening (if you lend your car to someone, do you sign the title over to him?).
So, even though it might seem bad (design-wise, coding practices, etc.) to pull the reference (or even the raw pointer) out of the unique_ptr, it actually is not because it is perfectly in accordance with the ownership rules set by the unique_ptr. And then, of course, there are other nice advantages, like clean syntax, no restriction to only objects owned by a unique_ptr, and so.
Personally, I avoid pulling a reference from a pointer/smart pointer. Because what happens if the pointer is nullptr? If you change the signature to this:
bool func(BaseClass& base, int other_arg);
You might have to protect your code from null pointer dereferences:
if (the_unique_ptr)
func(*the_unique_ptr, 10);
If the class is the sole owner of the pointer, the second of Martinho's alternative seems more reasonable:
func(the_unique_ptr.get(), 10);
Alternatively, you can use std::shared_ptr. However, if there's one single entity responsible for delete, the std::shared_ptr overhead does not pay off.

Code Review question - should I allow this passing of an auto_ptr as parameter?

Consider the following example code which I have recently seen in our code base:
void ClassA::ExportAnimation(auto_ptr<CAnimation> animation)
{
... does something
}
// calling method:
void classB::someMethod()
{
auto_ptr<CAnimation> animation (new CAnimation(1,2));
ClassA classAInstance;
classAInstance.ExportAnimation(animation)
... do some more stuff
}
I don't like this - and would rather write it so:
void ClassA::ExportAnimation(CAnimation* animation)
{
... does something
}
// calling method:
void classB::someMethod()
{
auto_ptr<CAnimation> animation (new CAnimation(1,2));
ClassA classAInstance;
classAInstance.ExportAnimation(animation.get())
... do some more stuff
}
but it is really a problem?
It all depends on what ExportAnimation is and how it is implemented.
Does it only use the object for the duration of the call and then leaves it?
Then convert to a reference and pass a real reference. There is no need to pass membership and the argument is not optional, so void ExportAnimation( CAnimation const & ) suffices. The advantage is that it is clear from the interface that there is no memory management issues with the method, it will just use the passed object and leave it as such. In this case, passing a raw pointer (as in your proposed code) is much worse than passing a reference in that it is not clear whether ExportAnimation is or not responsible for deletion of the passed in object.
Does it keep the object for later use?
This could be the case if the function starts a thread to export the animation in the background. In this case, it has to be clear that the lifetime of the argument must extend beyond the duration of the call. This can be solved by using shared_ptr --both in the function and outside of it-- as they convey the object is shared and will be kept alive as much as required meaning. Or else you can actually transfer ownership.
In the later case, if transfer of ownership is performed, then the initial code is fine --the signature is explicit in the ownership transfer. Else you can opt to document the behavior, change to a raw pointer and make the transfer explicit by calling ExportAnimation( myAnimation.release() ).
You have added some concerns as a comment to another answer:
can I really see that object no longer exists after the method call?
The caller auto_ptr is reset to 0 in the call, so any dereference will kill be an error and will be flagged in the first test you try.
I would need to look at the header file to see that the parameter type is an auto_ptr and not a normal pointer.
You do not need to look at the header... just try passing a raw pointer and the compiler will tell you that it requires an auto_ptr<> --There is no implicit conversion from raw pointer to auto_ptr.
I would expect the object to exist until the auto_ptr goes out of scope.
The standard auto_ptr, unlike boost::scope_ptr, do not have that semantics. The ownership of the object can be released or passed to other auto_ptr, so the assumption that an object held in an auto_ptr lives for the whole scope of the auto_ptr is bad in itself.
The auto_ptr unambiguously declares that the ownership of the pointer is passed on. The plain pointer isn't self-documenting.
What is the point of an auto-ptr if you only use its internals as a storage location?
Yes, pass it to the function. Or do away with it entirely, if you really don't want it. Presumably the function needs it to pass along ownership to something else.
It sounds like maybe the alternative you're looking for is much simpler:
void ClassA::ExportAnimation(CAnimation &animation) // no pointer
// calling method:
void classB::someMethod()
{
CAnimation animation(1,2); // no pointer
ClassA classAInstance;
classAInstance.ExportAnimation(animation) // no ownership tranfer
... do some more stuff
// object dies here, no earlier, no later
}
Passing the smart pointer to ExportAnimation clearly documents, and enforces, that ownership has been passed to the function, and there is no need for the caller to delete the animation. The function will also not need to explicitly delete the object, just let the pointer go out of scope.
Your suggestion leaves that ambigious; should ExportAnimation delete the object you've passed via raw pointer? You'd need to check the function's documentation to know what the caller should do, and also check the implementation to make sure it's actually implemented as documented.
I would always recommend using smart pointers (and other RAII idioms) to make object lifetime explicit and automatic.