0

I'm moving from java to c++ and and as I learn how things are done in C++, I sometimes get confused. I read online that if an object is created inside of a function it only exist inside the function unless it's declared using new. So I wrote the following code to test it:

#include <iostream>
using namespace std;

class Student{
private:
    int ID;
    int score;
public:
    void setID(int num);
    int getID();
    void setScore(int num);
    int getScore();
};
void Student::setID(int num)
{
    ID = num;
}

int Student::getID()
{
    return ID;
}
void Student::setScore(int num)
{
    score = num;
}

int Student::getScore()
{
    return score;
}

class Creator
{
public:
    static int nextID;
    Student getObject();
};
int Creator::nextID = 0;
Student Creator::getObject()
{
    Creator::nextID++;
    Student temp;
    temp.setID(Creator::nextID);
    return temp;
}

int main()
{
    Creator maker;
    Student pupil[4];

    for(std::size_t i = 0; i < (sizeof(pupil)/sizeof(pupil[0])); i++)
    {
        pupil[i] = maker.getObject();
    }

    for(std::size_t i = 0; i < (sizeof(pupil)/sizeof(pupil[0])); i++)
    {
        cout<< "Sudent ID: "<<pupil[i].getID()<<endl;
    }    

    int mark = 70;
    for(std::size_t i = 0; i < (sizeof(pupil)/sizeof(pupil[0])); i++)
    {
        pupil[i].setScore(mark);
        mark += 10;
    }

    for(std::size_t i = 0; i < (sizeof(pupil)/sizeof(pupil[0])); i++)
    {
        cout<< "Sudent ID: "<<pupil[i].getID()<<" has score of: "<<pupil[i].getScore()<<endl;
    }
    return 0;
}

The program works as expected and that is what is confusing me. According to what I read the object created inside of Student Creator::getObject() should not exist outside of it. It's destroyed as the function returns. Yet, I'm returning the object that was created inside of Student Creator::getObject() and storing it in the pupil array, outside of Student Creator::getObject().

Since it works, does it mean that the object was created on the heap? From what I read, if the object is created inside of a function and the new keyword wasn't used the object is created in the stack and destroyed as the function exits.

WhatIf
  • 653
  • 2
  • 8
  • 18
  • *"I read online that if an object is created inside of a function it only exist inside the function unless it's declared as an object."* How can an object created not be an object? – juanchopanza Feb 27 '16 at 00:13
  • sorry, meant unless it's declared using the new keyword – WhatIf Feb 27 '16 at 00:15
  • How come I can do `int f() {int i = 7; return i;} void f2() {int x = f(); System.out.println(x);}` in Java and it prints 7? Isn't `i` destroyed as the function returns? – user253751 Feb 27 '16 at 00:16
  • Please don't confuse scope with lifetime, they are two different things. – n. m. could be an AI Feb 27 '16 at 00:20
  • @immibis fundamental types in Java are on the heap and can therefore be returned as values. I think Integer behaves like an int and is an Object so is created on the heap and reference-counted. – stellarpower Feb 27 '16 at 00:47
  • @stellarpower I never said anything about Integer, and also Integer isn't a primitive ("fundamental") type in Java. – user253751 Feb 27 '16 at 00:54
  • @immibis That's what I'm saying. AFAIK the int is destroyed but like in C++ it is copied by value (unless optimised) out of the function into x and printed. However, if you had used the Integer class, things would be different and as you say, the Integer would have been cleaned-up by the garbage collector, because it is an object and so on the heap (I think) – stellarpower Feb 27 '16 at 12:24

5 Answers5

2

Regarding this function:

Student Creator::getObject()
{
    Creator::nextID++;
    Student temp;
    temp.setID(Creator::nextID);
    return temp;
}

What this is actually doing is creating a COPY of the returned value, using the class' copy constructor. The temp variable is is indeed removed off of the stack.

What you can't do, is this:

Student& Creator::getObject()
{
    Creator::nextID++;
    Student temp;
    temp.setID(Creator::nextID);
    return temp; // <- trying to return a reference transient memory
}
Colin Basnett
  • 4,052
  • 2
  • 30
  • 49
1

Since it works, does it mean that the object was created on the heap?

No. Nothing is dynamically allocated automatically (on the heap) unless you call new Student()

From what I read, if the object is created inside of a function and the new keyword wasn't used the object is created in the stack and destroyed as the function exits.

That's fundamentally true, though you can return a copy of that object as your function's return value, and let the compiler to decide for return value optimization.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Is the correct syntax to create an object on the heap new Student() or new Student? I came across code where the parentheses weren't included. – WhatIf Feb 27 '16 at 17:33
  • @WhatIf The correct method to create a `Student` instance on _the heap_ (it's actually called dynamic storage allocation, c++ doesn't have a notion of _heap_) is `new Student()`, yes. – πάντα ῥεῖ Feb 27 '16 at 17:39
  • What is the use of new Student? Does it also create an object? – WhatIf Feb 27 '16 at 17:41
  • @WhatIf Yes, it creates an object, but it's not recommended you use `new` directly yourself. Rather use smart pointers or containers. – πάντα ῥεῖ Feb 27 '16 at 17:44
0

Look at your signature for getObject

Student Creator::getObject()

getObject returns a copy of whatever you return. It is true that temp will be destructed once your function exits but you are not returning the reference to temp, you are returning the value of temp.

NickLamp
  • 862
  • 5
  • 10
0

In Java, AFAIK all objects are created on the heap and Java reference-counts the objects for you. In C++, if you instantiate an object, then you are correct, it is created on the stack, unless you, or a function you call, use new. So:

Student s; // On stack

Student *sp = new Student; //On heap

Student &sr = *new Student; //On heap

In C++, all objects on the stack are destroyed when they go out of scope, so your object temp IS destroyed. In the code above, the objects pointed to/referenced by sp and sr remain when sp and sr themselves go out of scope. What happens is that a shallow copy (by default) is made of temp, and that is what is returned, after which temp itself is cleaned up. This is different from Java, where you are returning a reference. Actually, C++ is calling the copy-constructor to make a copy of temp, and by writing your own copy-ctor for Student, if your class held pointers or referencss, you cou.d make copies of these objects rather than just copying the pointer/reference, which is what happens with the default shallow copy.

stellarpower
  • 332
  • 3
  • 13
0

temp is created as a local variable, so its scope is indeed bound to the function. temp bites the big one at getObject's end.

But getObject returns a Student, not a reference or pointer to a Student. At this point all sorts of cool things can happen at the whim of the compiler. temp could be copied, but since temp will never be used again in getObject it also could be moved. In some circumstances temp could be elided. The compiler will do whatever it deems the best option.

The best part is you probably won't even care.

user4581301
  • 33,082
  • 7
  • 33
  • 54