-2

I have been using Java since years. Now I need to understand a piece of C++ program.

TimeStamp theTimeStamp;
theTimeStamp.update();

What puzzles me is why don't we write

TimeStamp theTimeStamp = new(); 

My intuition is, to use an object, a memory space should be first allocated and associated with the object.

I guess this is a point where Java and C++ differ fundamentally? Could you clarify?

[EDIED] I wrote 'TimeStamp theTimeStamp = malloc();'

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
zell
  • 8,226
  • 7
  • 41
  • 91
  • It looks like there is a sort of new TimeStamp() that is called when theTimeStamp is declared. – Julien Oct 30 '13 at 08:38
  • 2
    @zell `TimeStamp theTimeStamp;` includes allocation and object construction. `theTimeStamp` itself is allocated on the hardware stack. You use `new` if you want that object on the free store. – greatwolf Oct 30 '13 at 08:40
  • The "memory space" is handled by the compiler. It knows the size of a `TimeStamp` object, just like it knows the size of an `int`. The object has automatic lifetime, meaning that it is bound to the scope it is declared in. If the object handles resource allocation, it must do so in its constructor and destructor. – juanchopanza Oct 30 '13 at 08:40
  • Voted down for what?? – zell Oct 30 '13 at 08:52
  • 2
    @zell: People are idiots and vote down any question now, simply because you didn't already know the answer. I'd ignore it. – Lightness Races in Orbit Oct 30 '13 at 08:57
  • 3
    @LightnessRacesinOrbit Perhaps it is to do with asking about `malloc` specifically. It shows little research effort. There is an interesting question somewhere in there though. – juanchopanza Oct 30 '13 at 09:00
  • 2
    C++ has a totally different object model from Java. In C++, variables are unconstrained, and variables can be objects. (But not every variable is an object, and an object doesn't have to be a variable.) This is all fundamental to the language and should be contained in any decent beginner's text book. (By contrast, Java variables (of non-primitive type) are *never* objects.) – Kerrek SB Oct 30 '13 at 09:08
  • Removing `[java]` as the answer doesn't have anything to do with Java. – Peter Lawrey Oct 30 '13 at 09:09
  • @zell just to add to Kerrek's comment. When you create an `int` or a `double` in java how would you do it? `int n = 42;` or `int n = new int(42);`? Obviously the former, yet memory space has to be carved out *somewhere* to hold that value -- so where does it go? If you understand that point then your above example should start to make more sense. – greatwolf Oct 30 '13 at 09:22
  • 1
    @KerrekSB In C++, every variable _is_ an object (but not all objects are variables). This is one of the fundamental differences between C++ and Java: in Java, "objects" must be dynamically allocated, variables are not objects, and there are special types which are not objects as well. In C++, you don't have all of these distinctions: practically speaking, everything that is not a function or a reference is an object; objects have (fundamentally) value semantics and unless dynamically allocated, language determined lifetime. – James Kanze Oct 30 '13 at 09:34
  • @JamesKanze: No, reference variables and variables of incomplete type are *not* objects. – Kerrek SB Oct 30 '13 at 09:35
  • @KerrekSB Ah yes. The standard does consider references to be variables as well. But you cannot have a non-reference variable to an incomplete type. (The distinction I was trying to make, of course, is that in Java, variables are _never_ objects, and that things like references or `int` are not objects either. Where as pointers---the C++ equivalent of Java's references---and `int` are objects in C++, and that there is fundamentally no difference in C++ between `int x;` and `MyType x;`.) – James Kanze Oct 30 '13 at 10:24
  • possible duplicate of [Why should \`new\` be used as little as possible?](http://stackoverflow.com/questions/6500313/why-should-new-be-used-as-little-as-possible) – nijansen Oct 30 '13 at 10:31
  • @JamesKanze: Sure you can: `extern int a[];` declares a variable `a`, but `a` is not an object. – Kerrek SB Oct 30 '13 at 10:35
  • 1
    @PeterLawrey: Tags are for the question, not the answers. Still, it's not relevant to the question either :) – Lightness Races in Orbit Oct 30 '13 at 10:38
  • @LightnessRacesinOrbit You have a point, but IMHO mentioning technologies you don't expect to be in the answer are not worth adding. – Peter Lawrey Oct 30 '13 at 11:01
  • **You don't know C++.** Pick a good C++ book and read it. Don't think that just because you've got some good answers to this particular question, you can continue "learning" C++ without _actually_ learning it. – Daniel Daranas Oct 30 '13 at 11:25
  • @KerrekSB `extern int a[]` declares a variable `a`, which _is_ an object (defined elsewhere). What makes you think that it isn't an object. – James Kanze Oct 30 '13 at 12:07
  • @JamesKanze: I figured that except within the translation unit which contains its definition, the variable `a` is certainly a variable, but you cannot use it as an object (e.g. evaluate it). But perhaps that isn't actually relevant. – Kerrek SB Oct 30 '13 at 13:03

4 Answers4

6

You would never write TimeStamp theTimeStamp = malloc(); in C++.

First, because malloc is from C and should really not be used in C++. Second, it is unaware of its context and needs a parameter to specify how much memory it must allocate, and returns an untyped pointer which you'd need to cast.

Instead you'd e.g. write

TimeStamp * theTimeStamp = new TimeStamp();

See - that's very similar to Java. Notice the * in there? That's for specifying that theTimeStamp is a pointer (in Java, every variable of a user-defined type is a pointer/reference, so you don't have to care about explicitly stating this).

In C++, however, you can choose whether you want

  • C++ to automatically handle the creation and destruction with the variable scope (i.e., without the *, as is done in your first code example). This means however, that as soon as theTimeStamp goes out of scope (i.e. usually at the end of the block where the variable is defined), the variable will be destroyed automatically.
  • Or if you want to do the dynamic memory allocation yourself (the default case in Java) - but in contrast to Java, you'd also have to care about the deletion of the object yourself in C++.

This having to take care about deletion "manually" is why in C++ usually such raw pointers are not used directly, but instead so called smart pointer types, e.g. std::shared_ptr from the new C++11 standard. They spare you the chore of having to do the deletion manually (and probably forgetting about it in many cases). There are other smart pointer types as well; the shared_ptr however provides the closest resemblance to what Java does - you can assign a shared_ptr to another, thereby keeping the object it points to alive, and only when the last of the shared pointer's pointing to an object is destroyed, will the object pointed to also be destroyed.

Whenever you can, it is however preferable in C++ to refrain from using pointers at all, and instead using automatically allocated variables.

codeling
  • 9,289
  • 4
  • 36
  • 61
  • I disagree with your last paragraph. Most pointers in C++ will also be raw pointers. The big difference in comparison with Java is that you do use value semantics; pointers (particularly as local variables) are relatively rare. – James Kanze Oct 30 '13 at 09:30
  • We've had this discussion many times, but I feel that you never should use a raw pointer to point to an object you need to clean up. – Puppy Oct 30 '13 at 18:40
3

Think of this in this way. In java when you want an int, you don't do

int i = new int(5);
i++;

You do

int i = 5;
i++;

In Java there is a distinction between a primitive and Objects. Primitives are allocated on the stack without new, and are destroyed at the end of scope. Objects are allocated with new and are garbage collected.

In C++ every class you write is by default like a primitive. It gets created on the stack, and gets destroyed at the end of scope. You can control what happens at creation and destruction by writing the Constructor and Destructor. Now this works great as long as your variables are limited by scope. When this is not the case, you can allocate the object of the class on the heap using new (old style) or make_unique/make_shared (modern style).

John Bandela
  • 2,296
  • 10
  • 18
2

In your example given, as no arguments are passed, the constructor of TimeStamp is called with no arguments to create a new TimeStamp on the stack. This variable will be deleted when its scope runs out (A new stack frame is used).

malloc allocates an amount of memory passed as a parameter and returns a void* to a block of that size. This memory is allocated on the heap, and will not be deleted when the scope runs out, and must be freed explicitly.

Seeing as this is C++ however, you do not want to be using malloc and free, you should instead stick to the friendly C++ variants new and delete.

Sinkingpoint
  • 6,806
  • 2
  • 24
  • 42
  • 1
    Except you shouldn’t use `new` and `delete` directly; you should use abstractions that do that for you (such as `std::vector` and `std::make_unique`). :) – rightfold Oct 30 '13 at 08:44
2

An automatic variable is a variable which is allocated and deallocated automatically when program flow enters and leaves the variable's context.

All variables declared within a block of code are automatic by default.

So when the flow reaches

TimeStamp theTimeStamp;

it automatically allocates this object on the stack using default constructor. The destructor is invoked automatically too, when the flow reaches }

You can also allocate it using dynamic memory:

TimeStamp *theTimeStamp = new TimeStamp(); //calling default constructor

And delete theTimeStamp; manually.

Never use malloc or free to allocate the class variable(object).

  • 1
    finally, someone who cares to mention automatic varaibles – thecoshman Oct 30 '13 at 08:58
  • 1
    *`TimeStamp theTimeStamp;` which is equivalent of `TimeStamp theTimeStamp();`* These are not equivalent. – Simple Oct 30 '13 at 10:05
  • @Simple so, could you explain why they are not – Alexey Teplyakov Oct 31 '13 at 08:44
  • @AlexeyTeplyakov change the name `theTimeStamp` in the second example to `getTimeStamp`. Now what does that look like? – Simple Oct 31 '13 at 09:38
  • @Simple I just notice interesting behavior: when I write `TimeStamp theTimeStamp(5);` - the constructor with an integer argument is invoked, but no one constructor is invoked with `TimeStamp theTimeStamp()` even the default one. Seems you're right, but I can't explain why. p.s. I fixed my answer – Alexey Teplyakov Oct 31 '13 at 12:50
  • 2
    @AlexeyTeplyakov Look at the signature of `TimeStamp theTimeStamp()` and then look at `TimeStamp getCurrentTime()`. They are both function declarations. Pedantically your edits aren't the same either. The second one requires that a non-deleted copy constructor be defined whereas the first doesn't. – Simple Oct 31 '13 at 13:00
  • @Simple 1) Why do say that they are both function declarations, though you, obviously, can't declare it within the another function (our case). I still dont get it :) 2) What about my fix: the second example `TimeStamp theTimeStamp = TimeStamp();` doesn't require the copy c'tor to be defined, the variable still initialized by default c'tor, compare it to `TimeStamp theTimeStamp(anotherStamp);` where the copy c'tor is invoked – Alexey Teplyakov Oct 31 '13 at 14:48
  • 1
    @AlexeyTeplyakov You can declare functions inside of other functions but you can't *define* them inside of other functions. Anything that can be parsed as a function declaration *is* a function declaration. So they are both function declarations. – Simple Oct 31 '13 at 14:51
  • @AlexeyTeplyakov `TimeStamp theTimeStamp = TimeStamp();` requires a non-deleted copy/move constructor and a default constructor to be defined. **The `=` here is not an assignment; it is calling the copy constructor**. `TimeStmap theTimeStamp;` requires only a default constructor. `TimeStamp theTimeStamp; theTimeStamp = TimeStamp();` is not copy construction; this is a default construction followed by a copy/move assignment from a value-initialised temporary. – Simple Oct 31 '13 at 14:52
  • @Simple I just checked it out, that during `TimeStamp theTimeStamp = TimeStamp();` copy c'tor is not invoked. Only the default one is. – Alexey Teplyakov Oct 31 '13 at 14:55
  • @AlexeyTeplyakov the copy constructor *may not be called but it needs to be defined and not be deleted*. The copy constructor will most probably be elided and the variable will just be default constructed. You can see this quite clearly with this example: http://ideone.com/Ctj6yy Notice how it requires the copy constructor to be callable, even though it might not actually call it. – Simple Oct 31 '13 at 14:57
  • @Simple hmm.. My gcc 4.7.2 doesn't require it and even doesn't complain about. We should read the standard states. – Alexey Teplyakov Oct 31 '13 at 15:02
  • @AlexeyTeplyakov the standard is very clear about this and this has been the case since 1998. You must not be using the code I provided because GCC **4.6** complains and errors. – Simple Oct 31 '13 at 15:04
  • @AlexeyTeplyakov Example showing function declaration: http://ideone.com/SHAGxj Example showing default construction: http://ideone.com/LrpyUZ Example showing default construction **+ require copy constructor (that may or may not be called)**: http://ideone.com/Ctj6yy – Simple Oct 31 '13 at 15:14
  • @Simple I got it, thank you for the explanation, I think GCC didn't complain because my copy c'tor wasn't declared as deleted, so the default copy c'tor always been there. Is there a situation where the function declaration inside another function could be useful? – Alexey Teplyakov Nov 01 '13 at 06:58
  • @AlexeyTeplyakov it's not really useful at all, but it was in C so C++ inherited it. It does have an effect on name lookup when combined with ADL but there are easier ways to achieve that. – Simple Nov 01 '13 at 08:56
  • Simple well, thank you, it was the super-duper conversation :) – Alexey Teplyakov Nov 01 '13 at 10:50