4

I am learning C++. I have C, C#, ObjC background. Pretty higher level languages.

On C# or ObjC , it's trivial returning heap allocated object as a result of a function or method. Because the cleanup of objects are managed (by convention). It will be destroyed at proper time.

But I don't know how should I handle this in C++.

For example,

std::string* makeString()
{
    std::string* str = GetSomeStringFromArbitrarySource ();
    SaveSomewhereElseInternally (str);
    return str;
}
void useString ()
{
    std::string* str = makeString ();

    // Where and how should I cleanup the `str` object?
    // It is not safe `delete str` here because it may be used on another place.
}

What is the recommended and conventional way to cleanup heap allocated object when it is passed over many functions?

I looked several smart pointers, but they don't look really reduce complexity or things to care. Am I misunderstanding the smart pointers?

trincot
  • 317,000
  • 35
  • 244
  • 286
eonil
  • 83,476
  • 81
  • 317
  • 516
  • This link (http://stackoverflow.com/questions/147130/why-doesnt-c-have-a-garbage-collector) has some very good information about C++ garbage collection, and specific information about it in the new standard (C++11). I know that's not a good answer, but hey, it's something. :) – L0j1k Feb 28 '13 at 01:49
  • 1
    Why not just `std::string makeString()` and `std::string str = makeString();`? Why use heap objects at all? – David Schwartz Feb 28 '13 at 01:53
  • @DavidSchwartz because he came from C#, and writes code like in C# – Slava Feb 28 '13 at 02:02
  • @Slava To be fair, using pointers is really not like C# either ;) – Reed Copsey Feb 28 '13 at 02:05
  • @ReedCopsey as much as I know (I am not a C# expert) all objects there created by new. So he probably just found where to keep result of new in C++ and used that. – Slava Feb 28 '13 at 02:09
  • @DavidSchwartz Actually, I used `std::string` only for an example, and my original intention was about all generic heap allocated objects. I couldn't expect these responses because I am newbie on C++... – eonil Feb 28 '13 at 03:21

5 Answers5

3

I looked several smart pointers, but they don't look really reduce complexity or things to care. Am I misunderstanding the smart pointers?

Most likely, yes. In C++, since you have to handle this yourself (no GC will clean it up for you), you need a way to track the usage of each and every object.

You can manually match every new with a delete, but this is sometimes difficult or impossible, such as in your scenario above. There is no way to know whether the object is being used elsewhere.

Smart pointers solve this by managing the lifetime for you, so you don't need to delete. They use various mechanisms to track how many places the object is being used, and call delete when the last one is done.

That being said, there isn't much reason in this specific case to use pointers at all. If you're working with std::string, you can pass the string around by value and it will never be an issue.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

You need to figure out the desired lifetime for your objects, and then use the type system to enforce that lifetime.

From your example, it isn't at all clear when you want the object to be destroyed.

In C++, it is common for objects to be passed around by value (as primitive types are in Java/C#/etc), so unless you have some need to share the std::string between different pieces of code, the usual thing would be to just return the string by value (write makeString as std::string makeString()).

If you do need to have multiple places referencing the same object, you should think carefully about the design, and decide what single part of the program can safely control the lifetime of the object. Create the object by value in that place, and then pass pointers and references elsewhere.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
2

You are misunderstanding the smart pointers most probably by the same reason why you wrote:

std::string* makeString()

Instead of what most C++ programmers would write instead:

std::string makeString()

You would need to better understand object lifetime in C++ and then smart pointers concept would be much easier.

Slava
  • 43,454
  • 1
  • 47
  • 90
1

Possibly you are misunderstanding smart pointers. In C++ the alternative is that the programmer needs to track the lifetime and usage of dynamically allocated objects. This affects the design of the software and also leads to human errors creeping in. When you use smart pointers , the lifetime of an object is pretty much taken care of for you.

I was brought up with the classical style of C++ (no smart pointers) and so I'm able to program that way , if required, but if you're starting out with c++ then smart pointers really is a must.

Rich
  • 4,572
  • 3
  • 25
  • 31
0

If you can use C++11 use shared pointers. These pointers implement a mechanism to delete the allocated object once the last of them is destroyed. If you are using C++03, use boost's shared pointers. If you can not use either, try to wrap heap allocations in classes you allocate on the stack, then pass references to those around, also give the RAII wiki a read.

David D
  • 1,571
  • 11
  • 12
  • 1
    Shared pointers are usually unnecessary, and they tend to add additional complexity because objects end up being shared between multiple different pieces of code, and so changes to those objects can have unexpected non-local effects. It is better to have a single clear owner if at all possible. – Mankarse Feb 28 '13 at 01:59
  • 1
    @Mankarse, I agree that any time there is an object that can be accessed by multiple other objects there is an implicit possibility of non-local side-effects. But, how is this different than creating the object in once place, and as you put it in your answer, "then pass pointers and references elsewhere"? – David D Feb 28 '13 at 02:07
  • 1
    In C++11, `std::unique_ptr` is more likely to be what he wants here. – Nemo Feb 28 '13 at 02:16
  • @David D: Obviously shared pointers have their uses, but they are rare. I guess the problem I have with this answer is the thought process -- "use shared pointers and all your problems will be solved". Whether you have a single owner or multiple owners, you still need to figure out the lifetimes of your objects and you still need to decide exactly which objects should get shared where, but once you've made these decisions, a `shared_ptr` based design does not communicate the decisions as well as a single owner based design. – Mankarse Feb 28 '13 at 02:19
  • 1
    @Nemo, When Eonil stated in his question "when it is passed over many functions," my mind went immediately to him storing them in multiple objects (for long term use), instead of just passing them along for use. From that perspective, I completely agree that unique_ptr is more apropo. – David D Feb 28 '13 at 02:43
  • I think the `std::shared_ptr` was exactly what I wanted. – eonil Feb 28 '13 at 04:21