Clear map of dynamic values in C++ - c++

I've seen many sites talking about the correct way to implement a d'tor for a class that holds a map.
But not for the case where the values of the map themselves are dynamically allocated.
For example, let Manager be a class which hold map<int, User*> where User is some class which I'll allocate dynamically later.
By the rules of the exercise, it should handle a registerUser(string name) function, which creates a new User instance and adds it to the map.
Something like:
User* registerUser(std::string userName) {
User* pNewUser = new User(userName);
// Setting some stuff
auto ret = users.insert(std::pair<int, User*>(pNewUser->id, pNewUser));
// Finishing and returning a pointer to the new allocated User
}
AND TO THE QUESTION ITSELF:
Should the d'tor do something special beyond users.clear()?
Will the memory be freed successfully or shall I iterate over the elements and delete them?
Thank you in advance :)

Don't use pointers when you do not have to. The std::map already manages the lifetime of its elements for you:
struct User {
std::string name;
int id;
static int id_counter;
User(const std::string& name) : name(name),id(id_counter++) {}
};
struct manager {
std::map<int,User> users;
User& registerUser(std::string userName) {
User u(userName);
auto ret = users.emplace(u.id,u);
return ret.first->second;
}
};
If you are forced to use a std::map<int,User*> because of weird unrealistic exercise requirements (or because the map is supposed to hold polymorphic objects) and you cannot use smart pointers then you need to delete what you newed. The map only manages its elements, not what they might point to:
struct manager {
std::map<int,User*> users;
User& registerUser(std::string userName) {
User* u = new User(userName);
auto ret = users.emplace(u->id,u);
return *(ret.first->second);
}
~manager() {
for (const auto& user : users){
delete user.second;
}
}
// the compiler generated assignment and copy would not do the right thing
manager(const manager&) = delete;
manager& operator=(const manager&) = delete;
};
Not sure where you read about holding a map as member and needing to call clear(). That is non-sense. The map has a destructor that is called automatically and the map does already clean up after itself.
Last but not least, you need to read about the rule of 3 (What is The Rule of Three?), because a destructor alone is not sufficient to correctly manage raw pointers as members. As mentioned in a comment, when you copy the manager via the compiler generated copy constructor or assignment, bad things will happen. Note that this isnt the case with the first version above. When possible you should try to follow the rule of 0 (https://en.cppreference.com/w/cpp/language/rule_of_three scroll down).

Should the d'tor do something special beyond users.clear()?
In general that depends on how your code handles ownership of heap allocated objects; any time you call a constructor by new (aka allocate on the heap) you should be aware of wich component in your code takes ownership over the newly created object and in consequence is responsible for deletion of the object.
For this specific toyproblem your Manager class should also handle the deletion of the object by iterating over all elements in your favourite way and calling delete. Be aware some other component could still hold onto one of these User-pointers wich will cause a crash by accessing invalid memory in the best case and running fine until it shipped in the worst case (or starting a nuclear war, since this is in the scope of undefined behaviour). The state of the art solution is using some kind of smart pointer.
Of course as 463035818_is_not_a_number put it so nicely in his answer you don't need to call users.clear(). Since the map will be deleted automagically since it is a statically allocated variable (but not necessarily the contents of the map).

Related

Confused by vectors of classes: "The Big Three", deleting a class after a push_back, and resource management

I have a class like this:
class cSerialMessage
{
public:
cSerialMessage(const enumMessages type, std::string txmessage = "") {rxAnswer="";};
// Get/Set Methods
// ...
bool AddIntParam(); // Stores an int as parameter for the message
void BuildCompleteMessage() // Build the whole message following the protocol rules
private:
enumMessages m_type;
std::string m_txmessage, m_rxanswer;
// [...]
};
Then i have another class which "manages" a queue of messages:
class cMsgManager
{
public:
cMsgManager();
// [...]
cSerialMessage* NewMessage(eMessages MSG);
bool AddParameter(int Param);
bool QueueMessage(bool FirstPosition);
private:
deque<cSerialMessage> cMS;
cSerialMessage* tempMsg;
}
The relevant part is where the cSerialMessage are created and added to the deque.
cSerialMessage* cMsgManager::NewMessage (eMessages MSG)
{
// Begin the creation of a new message
if (tempMsg!=nullptr) {
// there was already a temporary message
OutputDebugString ("NOPE!");
return nullptr;
}
tempMsg = new cSerialMessage(MSG);
return tempMsg;
}
//------------------------------------------------------------------------------
bool cMsgManager::AddParameter (int Param)
{
if (tempMsg==nullptr) {
// this means that NewMessage() was'nt called before.
OutputDebugString ("NOPE!);
return false;
}
return tempMsg->AddIntParam(Param);
}
//------------------------------------------------------------------------------
bool cMsgManager::QueueMessage(bool FirstPosition)
{
if (tempMsg==nullptr) {
// this means that NewMessage() was'nt called before.
OutputDebugString ("NOPE!);
return false;
}
// Build the final message
tempMsg->BuildCompleteMessage();
if (FirstPosition) {
cMS.push_front(*tempMsg);
}else{
cMS.push_back(*tempMsg);
}
delete tempMsg;
tempMsg=nullptr;
return true;
}
Despite all the questions about this topic ( this is very detailed), i'm still confused.
Should i delete my tempMsg? Is it copyed in the deque or, in the end, the data pointed by tempMsg are the one that will be later accessed from the deque?
Or have i to create the copy-constructor and copy-assignement operator?
Should i delete my tempMsg?
Yes, as written, you must either delete your tempMsg, or reuse the single instance for the life of the program (no making new ones after the first). Reusing it would likely require clearing it out before each reuse, which hardly seems worth it.
Is it copyed in the deque or, in the end, the data pointed by tempMsg are the one that will be later accessed from the deque?
It's copied; push_back receives references, but is documented only to copy or move (and since you passed an l-value, it's going to copy). You could save a little work by doing cMS.push_front(std::move(*tempMsg)); so as to empty out tempMsg (since you're just going to delete it after, so you may as well save the copies).
Or have i to create the copy-constructor and copy-assignement operator?
Assuming all the members of your cSerialMessage are themselves properly copyable (no raw pointers or the like), and you haven't defined any custom copy/move operations or destructors, you should be fine; the compiler generated copy constructor will work fine. cMsgManager on the other hand would need the full Rule of 3/5 constructors and destructors, because you didn't use a smart pointer or value semantics for tempMsg.
Note that this whole dynamic allocation thing is pointless/wasteful. You could just make tempMsg a cSerialMessage (not cSerialMessage*), and work with it by value. You could keep it an attribute of the instance, or just have NewMessage return the actual new message, not store a copy locally at all. The local copy is going to make threading or reentrant code a nightmare, so returning a new message by value, and having the caller manage it is probably a better idea.
Should I delete tempMsg? Yes you created it, someone has to delete it, and that should be you.
Is it copied into the deque? No, what is pointed to by tempMsg is copied into the deque, but tempMsg is still there afterwards and the object it points to is still there and so it needs deleting.
Do I have to create the copy-constructor and copy-assignment operator? Yes, or mark them as deleted if you are happy with cMsgManager being uncopyable.

Remember the original object which is merely able to manage shared memory

I have a question about good C++ style:
I would like to write a class "MyClass" which has one or some pointers as members and MyClass is able to allocate memory to this pointers. I would like to use the implicit give default-copy-constructor (as well as the default-assignement-operator) to copy an instance of MyClass, so that only the pointers were copied and the new object share the data which the initial object has allocated.
My idea was to prohibit copied objects (created with copy constructor or assignment operator) to release memory (as well as allocate memory to member pointers). In order to distinguesh between copied objects and original objects (created by the constructor), I want to use the following code:
class MyClass
{
public:
MyClass(): originalPtr(this) { data = new char[100000]; }
~MyClass() { if(originalPtr == this) delete[] data; }
private:
MyClass *originalPtr;
char *data; // shared data (not copiable)
char otherFeatures[10]; // individual data (copiable)
};
Would this solution (using the comparison with the this-pointer) a good style for such a purpose (e.g. parsing an object by call by value) or is it risky? Of course, I assume that the original object live always longer than the copied objects.
Thank you!
No, this is a bad idea. If the pointers are shared by several instances, than the one to deallocate should be the last one to die, not the original one. This differs in the sense that the original one might not be the one to die, which would cause all others to be pointing at garbage. Even though you assume that it's the last one to die, you need to realise that the inner workings of a class should not rely on external assumptions. That is, the class has no guarantees on how its life span is managed by the rest of the implementation, so it shouldn't make assumptions.
In this situation you should track references to your data. The basic idea is to keep track of how many copies of the class you have. As soon as that count reaches zero, you are free to release that memory; the last copy has just died. Fortunately for you, STL already provides such an implementation. These are known as Smart Pointers. There are others, such as std::unique_ptr, which makes the opposite by ensuring that the data is owned only by a single instance.
Ok, assuming the general case, where the original object does not die at last. I like the idea to just count the instances. For example one could use such a concept:
class MyClass
{
public:
MyClass(): countOfInstances(new int())
{
++*countOfInstances;
data = new char[100000];
}
~MyClass()
{
--*countOfInstances;
if(!countOfInstances)
{
delete[] data;
delete countOfInstances;
}
}
MyClass(const MyClass &other) // analogous for the assignment operator
{
countOfInstances = other.countOfInstances;
data = other.data;
otherFeatures = other.otherFeatures;
++*countOfInstances;
}
private:
int *countOfInstances;
char *data; // shared data (not copiable)
char otherFeatures; // individual data (copiable)
};
Here, one should also make sure that the shared memory is completely allocated before allowing to make copies.

Accessing Members of Containing Objects from Contained Objects

If I have several levels of object containment (one object defines and instantiates another object which define and instantiate another object..), is it possible to get access to upper, containing - object variables and functions, please?
Example:
class CObjectOne
{
public:
CObjectOne::CObjectOne() { Create(); };
void Create();
std::vector<ObjectTwo>vObejctsTwo;
int nVariableOne;
}
bool CObjectOne::Create()
{
CObjectTwo ObjectTwo(this);
vObjectsTwo.push_back(ObjectTwo);
}
class CObjectTwo
{
public:
CObjectTwo::CObjectTwo(CObjectOne* pObject)
{
pObjectOne = pObject;
Create();
};
void Create();
CObjectOne* GetObjectOne(){return pObjectOne;};
std::vector<CObjectTrhee>vObjectsTrhee;
CObjectOne* pObjectOne;
int nVariableTwo;
}
bool CObjectTwo::Create()
{
CObjectThree ObjectThree(this);
vObjectsThree.push_back(ObjectThree);
}
class CObjectThree
{
public:
CObjectThree::CObjectThree(CObjectTwo* pObject)
{
pObjectTwo = pObject;
Create();
};
void Create();
CObjectTwo* GetObjectTwo(){return pObjectTwo;};
std::vector<CObjectsFour>vObjectsFour;
CObjectTwo* pObjectTwo;
int nVariableThree;
}
bool CObjectThree::Create()
{
CObjectFour ObjectFour(this);
vObjectsFour.push_back(ObjectFour);
}
main()
{
CObjectOne myObject1;
}
Say, that from within CObjectThree I need to access nVariableOne in CObjectOne. I would like to do it as follows:
int nValue = vObjectThree[index].GetObjectTwo()->GetObjectOne()->nVariable1;
However, after compiling and running my application, I get Memory Access Violation error.
What is wrong with the code above(it is example, and might contain spelling mistakes)?
Do I have to create the objects dynamically instead of statically?
Is there any other way how to achieve variables stored in containing objects from withing contained objects?
When you pass a pointer that points back to the container object, this pointer is sometimes called a back pointer. I see this technique being used all the time in GUI libraries where a widget might want access to its parent widget.
That being said, you should ask yourself if there's a better design that doesn't involve circular dependencies (circular in the sense that the container depends on the containee and the containee depends on the container).
You don't strictly have to create the objects dynamically for the back pointer technique to work. You can always take the address of a stack-allocated (or statically-allocated) object. As long as the life of that object persists while others are using pointers to it. But in practice, this technique is usually used with dynamically-created objects.
Note that you might also be able to use a back-reference instead of a back-pointer.
I think I know what's causing your segmentation faults. When your vectors reallocate their memory (as the result of growing to a larger size), the addresses of the old vector elements become invalid. But the children (and grand-children) of these objects still hold the old addresses in their back-pointers!
For the back-pointer thing to work, you'll have to allocate each object dynamically and store their pointers in the vectors. This will make memory management a lot more messy, so you might want to use smart pointers or boost::ptr_containers.
After seeing the comment you made in another answer, I now have a better idea of what you're trying to accomplish. You should research generic tree structures and the composite pattern. The composite pattern is usually what's used in the widget example I cited previously.
Maybe all your object can inherit from a common interface like :
class MyObject
{
public:
virtual int getData() = 0;
}
And after you can use a std::tree from the stl library to build your structure.
As Emile said, segmentation fault is caused by reallocation. Exactly speaking -- when the local stack objects' 'this' pointer was passed to create another object, which is then copied to the vector container. Then the 'Create()' function exits, the stack frame object ceases to exist and the pointer in the container gets invalid.

Classes, constructor and pointer class members

I'm a bit confused about the object references. Please check the examples below:
class ListHandler {
public:
ListHandler(vector<int> &list);
private:
vector<int> list;
}
ListHandler::ListHandler(vector<int> &list) {
this->list = list;
}
Because of the internal
vector<int> list;
definition, here I would be wasting memory right? So the right one would be:
class ListHandler {
public:
ListHandler(vector<int>* list);
private:
vector<int>* list;
}
ListHandler::ListHandler(vector<int>* list) {
this->list = list;
}
ListHandler::~ListHandler() {
delete list;
}
Basically all I want is to create a vector and pass to ListHandler. This vector will not be used anywhere else than the ListHandler itself so I'm expecting ListHandler to do all the other things and cleanup etc. stuff.
It depends on whether you want to share the underyling vector or not. In general, I think it is a good practice to avoid sharing wherever possible, since it removes the question of object ownership. Without sharing:
class ListHandler
{
public:
ListHandler(const std::vector<int>& list) : _list(list) {}
~ListHandler(){}
private:
std::vector<int> _list;
};
Note that, unlike in your example, I make it const since the original will not be modified. If, however, we want to hang on to and share the same underlying object, then we could use something like this:
class ListHandler
{
public:
ListHandler(std::vector<int>& list) : _list(&list) {}
~ListHandler(){}
private:
std::vector<int>* _list;
};
Note that in this case, I choose to leave the caller as the owner of the object (so it is the caller's responsiblity to ensure that the list is around for the lifetime of the list handler object and that the list is later deallocated). Your example, in which you take over the ownership is also a possibility:
class ListHandler
{
public:
ListHandler(std::vector<int>* list) : _list(list) {}
ListHandler(const ListHandler& o) : _list(new std::vector<int>(o._list)) {}
~ListHandler(){ delete _list; _list=0; }
ListHandler& swap(ListHandler& o){ std::swap(_list,o._list); return *this; }
ListHandler& operator=(const ListHandler& o){ ListHandler cpy(o); return swap(cpy); }
private:
std::vector<int>* _list;
};
While the above is certainly possible, I personally don't like it... I find it confusing for an object that isn't simply a smart pointer class to acquire ownership of a pointer to another object. If I were doing that, I would make it more explicit by wrapping the std::vector in a smart pointer container as in:
class ListHandler
{
public:
ListHandler(const boost::shared_ptr< std::vector<int> >& list) : _list(list) {}
~ListHandler(){}
private:
boost::shared_ptr< std::vector<int> > _list;
};
I find the above much clearer in communicating the ownership. However, all these different ways of passing along the list are acceptable... just make sure users know who will own what.
The first example isn't necessarily wasting memory, its just making a copy of the entire vector at the "this->list = list;" line (which could be what you want, depends on the context). That is because the operator= method on the vector is called at that point which for vector makes a full copy of itself and all its contents.
The second example definitely isn't making a copy of the vector, merely assigning a memory address. Though the caller of the ListHandler contructor better realize that ListHandler is taking over control of the pointer, since it will end up deallocating the memory in the end.
It depends on whether the caller expects to keep using their list (in which case you better not delete it, and need to worry about it changing when you least expect), and whether the caller is going to destroy it (in which case you better not keep a pointer to it).
If the documentation of your class is that the caller allocates a list with new and then turns ownership over to your class when calling your constructor, then keeping the pointer is fine (but use auto_ptr so you don't have to write "delete list" yourself and worry about exception safety).
It all depends what you want, and what policies you can ensure. There is nothing "wrong" with your first example (though I would avoid explicitly using this-> by choosing different names). It makes a copy of the vector, and that may be the right thing to do. It may be the safest thing to do.
But it looks like you would like to reuse the same vector. If the list is guaranteed to outlive any ListHandler, you can use a reference instead of a pointer. The trick is that the reference member variable must be initialized in an initialization list in the constructor, like so:
class ListHandler
{
public:
ListHandler(const vector<int> &list)
: list_m(list)
{
}
private:
vector<int>& list_m;
};
The initialization list is the bit after the colon, but before the body.
However, this is not equivalent to your second example, which using pointer and calls delete in its destructor. That is a third way, in which the ListHandler assumes ownership of the list. But the code comes with dangers, because by calling delete it assumes the list was allocated with new. One way to clarify this policy is by using a naming convention (such as an "adopt" prefix) that identifies the change of ownership:
ListHandler::ListHandler(vector<int> *adoptList)
: list_m(adoptList)
{
}
(This is the same as yours, except for the name change, and the use of an initialization list.)
So now we have seen three choices:
Copy the list.
Keep a reference to a list that someone else owns.
Assume ownership of a list that someone created with new.
There are still more choices, such as smart pointers that do reference counting.
There's no single "right way." Your second example would be very poor style, however, because the ListHandler acquires ownership of the vector when it is constructed. Every new should be closely paired with its delete if at all possible — seriously, that is a very high priority.
If the vector lives as long as the ListHandler, it might as well live inside the ListHandler. It doesn't take up any less space if you put it on the heap. Indeed, the heap adds some overhead. So this is not a job for new at all.
You might also consider
ListHandler::ListHandler(vector<int> &list) {
this->list.swap( list );
}
if you want the initializer list to be cleared and avoid the time and memory overhead of copying the vector's contents.

C++ best practice: Returning reference vs. object

I'm trying to learn C++, and trying to understand returning objects. I seem to see 2 ways of doing this, and need to understand what is the best practice.
Option 1:
QList<Weight *> ret;
Weight *weight = new Weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return &ret;
Option 2:
QList<Weight *> *ret = new QList();
Weight *weight = new Weight(cname, "Weight");
ret->append(weight);
ret->append(c);
return ret;
(of course, I may not understand this yet either).
Which way is considered best-practice, and should be followed?
Option 1 is defective. When you declare an object
QList<Weight *> ret;
it only lives in the local scope. It is destroyed when the function exits. However, you can make this work with
return ret; // no "&"
Now, although ret is destroyed, a copy is made first and passed back to the caller.
This is the generally preferred methodology. In fact, the copy-and-destroy operation (which accomplishes nothing, really) is usually elided, or optimized out and you get a fast, elegant program.
Option 2 works, but then you have a pointer to the heap. One way of looking at C++ is that the purpose of the language is to avoid manual memory management such as that. Sometimes you do want to manage objects on the heap, but option 1 still allows that:
QList<Weight *> *myList = new QList<Weight *>( getWeights() );
where getWeights is your example function. (In this case, you may have to define a copy constructor QList::QList( QList const & ), but like the previous example, it will probably not get called.)
Likewise, you probably should avoid having a list of pointers. The list should store the objects directly. Try using std::list… practice with the language features is more important than practice implementing data structures.
Use the option #1 with a slight change; instead of returning a reference to the locally created object, return its copy.
i.e. return ret;
Most C++ compilers perform Return value optimization (RVO) to optimize away the temporary object created to hold a function's return value.
In general, you should never return a reference or a pointer. Instead, return a copy of the object or return a smart pointer class which owns the object. In general, use static storage allocation unless the size varies at runtime or the lifetime of the object requires that it be allocated using dynamic storage allocation.
As has been pointed out, your example of returning by reference returns a reference to an object that no longer exists (since it has gone out of scope) and hence are invoking undefined behavior. This is the reason you should never return a reference. You should never return a raw pointer, because ownership is unclear.
It should also be noted that returning by value is incredibly cheap due to return-value optimization (RVO), and will soon be even cheaper due to the introduction of rvalue references.
passing & returning references invites responsibilty.! u need to take care that when you modify some values there are no side effects. same in the case of pointers. I reccomend you to retun objects. (BUT IT VERY-MUCH DEPENDS ON WHAT EXACTLY YOU WANT TO DO)
In ur Option 1, you return the address and Thats VERY bad as this could lead to undefined behaviour. (ret will be deallocated, but y'll access ret's address in the called function)
so use return ret;
It's generally bad practice to allocate memory that has to be freed elsewhere. That's one of the reasons we have C++ rather than just C. (But savvy programmers were writing object-oriented code in C long before the Age of Stroustrup.) Well-constructed objects have quick copy and assignment operators (sometimes using reference-counting), and they automatically free up the memory that they "own" when they are freed and their DTOR automatically is called. So you can toss them around cheerfully, rather than using pointers to them.
Therefore, depending on what you want to do, the best practice is very likely "none of the above." Whenever you are tempted to use "new" anywhere other than in a CTOR, think about it. Probably you don't want to use "new" at all. If you do, the resulting pointer should probably be wrapped in some kind of smart pointer. You can go for weeks and months without ever calling "new", because the "new" and "delete" are taken care of in standard classes or class templates like std::list and std::vector.
One exception is when you are using an old fashion library like OpenCV that sometimes requires that you create a new object, and hand off a pointer to it to the system, which takes ownership.
If QList and Weight are properly written to clean up after themselves in their DTORS, what you want is,
QList<Weight> ret();
Weight weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return ret;
As already mentioned, it's better to avoid allocating memory which must be deallocated elsewhere. This is what I prefer doing (...these days):
void someFunc(QList<Weight *>& list){
// ... other code
Weight *weight = new Weight(cname, "Weight");
list.append(weight);
list.append(c);
}
// ... later ...
QList<Weight *> list;
someFunc(list)
Even better -- avoid new completely and using std::vector:
void someFunc(std::vector<Weight>& list){
// ... other code
Weight weight(cname, "Weight");
list.push_back(weight);
list.push_back(c);
}
// ... later ...
std::vector<Weight> list;
someFunc(list);
You can always use a bool or enum if you want to return a status flag.
Based on experience, do not use plain pointers because you can easily forget to add proper destruction mechanisms.
If you want to avoid copying, you can go for implementing the Weight class with copy constructor and copy operator disabled:
class Weight {
protected:
std::string name;
std::string desc;
public:
Weight (std::string n, std::string d)
: name(n), desc(d) {
std::cout << "W c-tor\n";
}
~Weight (void) {
std::cout << "W d-tor\n";
}
// disable them to prevent copying
// and generate error when compiling
Weight(const Weight&);
void operator=(const Weight&);
};
Then, for the class implementing the container, use shared_ptr or unique_ptr to implement the data member:
template <typename T>
class QList {
protected:
std::vector<std::shared_ptr<T>> v;
public:
QList (void) {
std::cout << "Q c-tor\n";
}
~QList (void) {
std::cout << "Q d-tor\n";
}
// disable them to prevent copying
QList(const QList&);
void operator=(const QList&);
void append(T& t) {
v.push_back(std::shared_ptr<T>(&t));
}
};
Your function for adding an element would make use or Return Value Optimization and would not call the copy constructor (which is not defined):
QList<Weight> create (void) {
QList<Weight> ret;
Weight& weight = *(new Weight("cname", "Weight"));
ret.append(weight);
return ret;
}
On adding an element, the let the container take the ownership of the object, so do not deallocate it:
QList<Weight> ql = create();
ql.append(*(new Weight("aname", "Height")));
// this generates segmentation fault because
// the object would be deallocated twice
Weight w("aname", "Height");
ql.append(w);
Or, better, force the user to pass your QList implementation only smart pointers:
void append(std::shared_ptr<T> t) {
v.push_back(t);
}
And outside class QList you'll use it like:
Weight * pw = new Weight("aname", "Height");
ql.append(std::shared_ptr<Weight>(pw));
Using shared_ptr you could also 'take' objects from collection, make copies, remove from collection but use locally - behind the scenes it would be only the same only object.
All of these are valid answers, avoid Pointers, use copy constructors, etc. Unless you need to create a program that needs good performance, in my experience most of the performance related problems are with the copy constructors, and the overhead caused by them. (And smart pointers are not any better on this field, I'd to remove all my boost code and do the manual delete because it was taking too much milliseconds to do its job).
If you're creating a "simple" program (although "simple" means you should go with java or C#) then use copy constructors, avoid pointers and use smart pointers to deallocate the used memory, if you're creating a complex programs or you need a good performance, use pointers all over the place, and avoid copy constructors (if possible), just create your set of rules to delete pointers and use valgrind to detect memory leaks,
Maybe I will get some negative points, but I think you'll need to get the full picture to take your design choices.
I think that saying "if you're returning pointers your design is wrong" is little misleading. The output parameters tends to be confusing because it's not a natural choice for "returning" results.
I know this question is old, but I don't see any other argument pointing out the performance overhead of that design choices.