6

In C++ (I use QT) I can create an instance of QString class two ways:

method 1

QString str = "my string";

method 2

QString *str = new QString("my string");

I know this is to do with pointers. So my questions are:

  1. what is the difference between the two?
  2. which method should I stick to?
  3. when is it correct to use method 1 and when is it correct to use method 2?
  4. in method 2 I can destroy the object by calling delete str;. How can I delete the str variable when using method 1?

Thanks

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
Roman
  • 10,309
  • 17
  • 66
  • 101

6 Answers6

5
  1. primarily they have different lifetimes: the object created in method 2 will live arbitrarily long until you call delete; in method 1 it will be created on the stack and be destroyed upon return from the function call (if any). secondarily method 2 requires more work because of non-trivial memory management.

  2. use the method that matches the lifetime you want. if the lifetime of method 1 is good enough for you do not use method 2 because it entails the overhead of memory management. if you can restructure your program so that you can do with method 1 while also improving on the design, that will be more efficient and elegant.

  3. see 2. above. in particular, using method 1 and storing a pointer to the object and accessing it after its lifetime is a pitfall. this is also possible with method 2 but the explicit destruction focuses the programmer's attention on it (but still because the lifetime is not straightforward it is a likely pitfall) a pitfall with method 2 is forgetting to delete it causing a memory leak (or deleting it too early and referring to it as described earlier in this paragraph)

  4. in method 1 the object will be automatically deleted when the function returns.

necromancer
  • 23,916
  • 22
  • 68
  • 115
  • What will happen if I return the object created using method 1 as the result of my function? Do I then need to free it or the compiler is smart enough to know when it should be freed? – Roman Dec 09 '11 at 01:17
  • 1
    if you do that you will have a significant bug in your program because the compiler will free it when your function returns the result -- regardless of whether you returned it as a result or not -- so you will be returning a pointer to nowhere – necromancer Dec 09 '11 at 01:20
  • 2
    That is assuming you are returning a pointer to the object. If you return the object itself... a copy will be made. – Daniel Placek Dec 09 '11 at 01:26
  • hmmm... i wonder what would be the lifetime of that (copied) object? – necromancer Dec 09 '11 at 01:35
  • @agksmehx the same as the lifetime of a normally copied object - it depends on how it is used. – Seth Carnegie Dec 09 '11 at 01:51
  • @Seth if a pointer is taken `QString * p = f();` what would be the lifetime of the object p is pointing to? additionally if `QString q = f();` would it be copied once directly to q? or twice, once to intermediate and then to q? – necromancer Dec 09 '11 at 01:56
  • 1
    @agksmehx the lifetime of the object `p` is pointing to would be that statement (the object would be destroyed at the end of the statement). `QString q = f()` is the same as `QString q(f());` so a temporary is constructed and passed to the copy constructor of `QString` and then the temporary is destroyed at the end of the statement. However, the compiler is free to optimise that away. – Seth Carnegie Dec 09 '11 at 02:34
5

The two are very different things.

QString str("my string"); creates an object whose lifetime is automatically managed: The object either lives to the end of its enclosing scope (if it is a local variable), or to the end of the program (if it is a global variable).

new QString("my string"); creates an object with manually managed lifetime, also called a "dynamic object" (and returns a pointer to this object). This means that you are responsible for managing the object's lifetime. This is almost never the right thing to do, unless you are writing a library component.

And here lies the heart of the C++ philosophy: C++ is a language for library writing. You have the tools to write high-quality, reusable components. If and when you do this, you will need to know the intricacies of lifetime management. However, until such time come, you should use existing library components. When doing so, you will find that you will almost never need to perform any manual management at all.

Use dynamic containers (vectors, strings, maps, etc.) to store data and build your own data structures. Pass arguments by reference if you need to modify objects in the caller's scope. Build complex classes from simpler components. If you really must have dynamic objects, handle them through unique_ptr<T> or shared_ptr<T> handler classes.

Don't use pointers. Rarely use new, and delete never.

(Further tips: 1) Never use using namespace unless it is for ADL. 2) Unless you are writing library components, well-designed classes should not have destructors, copy constructors or assignment operators. If they do, factor out the offending logic into a single-responsibility library component, then see 2).)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    I didn't downvote. But I will point out that saying "never use pointers" to someone who is using Qt is going to seem like confusing advice. Every Qt widget example is full of `new` calls, which aren't paired with deletes. I'd prefer it if addWidget took a QSharedPointer, but... http://stackoverflow.com/questions/1651616/qt-doesnt-cause-memory-leakwindow-cpp.html – HostileFork says dont trust SE Dec 09 '11 at 02:00
  • 2
    @HostileFork: Fair enough about Qt... but I guess that says more about Qt than about C++! I haven't worked with it in a while, and I wonder if it can't be improved by a generous dose of `unique_ptr`... hopefully, there'll be a C++11-revamp of Qt eventually that'll clean up a bit. Also note that the question, and hence my answer, is about "objects in C++", not about "Qt best practices". – Kerrek SB Dec 09 '11 at 09:41
  • They've announced that Qt5 isn't going to *require* C++11. Some people were calling for that, and I'd be one of them...but they're pragmatists. Still, Qt4.8 is already getting some under-the-hood improvements if you compile as C++0x/C++11. I'd be happy if the raw pointers being passed around in the QObject "ownership trees" were dropped and were replaced with smart pointers, QSharedPointer would be fine, but they're unlikely to do that big a shake-up of the interface anytime soon: http://doc.qt.nokia.com/4.7-snapshot/objecttrees.html – HostileFork says dont trust SE Dec 09 '11 at 10:02
  • @HostileFork: Thanks -- I guess they could/should have a Qt-style smart pointer class, and *internally* they could make it use a `unique_ptr` when possible, and a `tr1/shared_ptr` or whatever on C++98/03... those raw pointers are really an eye sore. Well, let's hope that Qt keeps getting maintained and developed! – Kerrek SB Dec 09 '11 at 10:05
  • 2
    There's nothing stopping you from using smart pointers in Qt (They even have their own QSharedPtr and QScopedPtr and so on, basically mimicking Boost's ones. But the Qt API relies heavily on raw pointers and on ownership being managed by specifying a "parent" for every object – jalf Dec 09 '11 at 13:08
  • 2
    Anyway, @KerrekSB's answer is definitely the correct one C++-wise. Qt suffers from an API designed a long time ago, by people who weren't too familiar with "modern" C++. They're sticking with an API that looks more like Java than C++, and just require you to work around the problems it causes. But even if you're using Qt, don't make the mistake of thinking that this is good C++ style – jalf Dec 09 '11 at 13:11
  • @KerrekSB: Sometimes it is appropriate for a non-resource-managing class to have an assignment operator which provides the strong exception safety guarantee. In this case it is necessary to manually provide one. – Mankarse Dec 10 '11 at 12:49
  • That's funny that this is the preferred C++ style now. You wouldn't have known it reading introductory C++ books 15 years ago. – daj Mar 29 '13 at 13:14
3

When you use first syntax, you are creating object whose name is str with a type of QString and an initial value of "my string".

In second declaration you create pointer of type QString whose name is str.

Pointers do not hold the value, they point on the memory location where the value is stored, and the difference is big.

competent_tech
  • 44,465
  • 11
  • 90
  • 113
MrD
  • 2,423
  • 3
  • 33
  • 57
2

Method one will use automatic memory management (the object will be deleted when it goes out of scope).

Method two is for manual memory management -- it won't be deleted until you call delete str; If you forget to delete it -- this creates what we call a memory leak!

Generally method one will be the best choice unless you have a reason to use a pointer. (less chance of mistakes)

You may find this helpful: Why use pointers?

Community
  • 1
  • 1
Daniel Placek
  • 765
  • 5
  • 16
2

The difference is that method one creates the QString on the stack and the second way creates the QString on the free store. (Note that QString s = "hello"; is exactly the same as QString s("hello");.) Like parapura rajkumar said, always do 1 when you can, and 2 when you can't do 1.

Method 1 has many advantages, not the least of which is automatic memory management. The memory occupied by that QString will be automatically released when it goes out of scope, so you don't need to do anything to deallocate its memory. Method 2 requires you to use delete when you are done with it to deallocate the memory, or you will have a memory leak.

Another advantage is that it is much faster to create something on the stack than on the free store.

A situation where you must use Method 2 is when you need that very object to last longer than the scope you are in. Then you'd allocate in on the free store with new so that it will last until you call delete on it, and then pass the pointer around.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • Can all classes be instantiated using method 1? – Roman Dec 09 '11 at 01:15
  • @Am. yes, if they have a public constructor (actually if they have an _accessible_ constructor; if you're a friend function then you can access even private constructors). If they don't have an accessible constructor, they can't be instantiated with method 2 either. – Seth Carnegie Dec 09 '11 at 01:17
1

when is it correct to use method 1 and when is it correct to use method 2?

In this example it is not obvious when you can use the pointer. But if you create your own class, for example Images, which holds a lot of data, and you want a pass object of that class in a function or method, then I suggest you to use pointer to an object not the object itself. Why? If you pass a pointer to a function you are passing only memory address of the object (you are copying few bytes), but if you are passing object itself, then you are passing a lots of data, which can slowdown you application.

Lets see another example: Lets say you have a function with three parameters, and function body should change every parameter when function ends. As you know, function can return only one value, so one way you can change every parameter in function body is to use pointers.

There are lots of reasons of using pointers, and you should be careful when using them. I suggest you reading few articles about that theme.

I hope you understood the difference. The key concept is difference between object address, and object itself!

MrD
  • 2,423
  • 3
  • 33
  • 57