Whenever you enter a scope, a stackframe is 'created'. Everything you allocate to this local stack will be destroyed (the destructors of all local stack objects is called, in reverse order of creation) when you exit the scope.
If you write your example like this, it becomes more obvious:
if (2 < 3)
{
Student p;
} // scope exit, p's destructor is called
If you want to create some unknown quantity of objects, you should use a container.
#include <vector>
std::vector<Student> students;
if (2 < 3)
{
Student p;
students.push_back(p);
}
// use students instead of p
Edit in response to comments:
Without using containers
#include <iostream>
#include <string>
class Student
{
public:
std::string lastname, firstname;
};
int main()
{
Student p; // p is default initialized with empty strings
if (2 < 3)
{
p = Student{"Lastname", "Firstname"}; // Assign a new student to p
} // p is not destroyed
std::cout << p.firstname << ' ' << p.lastname << std::endl;
return 0;
}
Using pointers you can create a new object on the free-store, but you have to remember to delete
it
#include <iostream>
#include <string>
class Student
{
public:
std::string lastname, firstname;
};
int main()
{
Student *p = (2 < 3) ? new Student : nullptr;
if(p != nullptr)
std::cout << p->firstname << ' ' << p->lastname << std::endl;
delete p; // Remember to clean up
return 0;
}
Using unique_ptr and RAII (Same as above, but the pointer is wrapped in a unique_ptr, which will delete your student automatically when it goes out of scope)
#include <iostream>
#include <string>
#include <memory>
class Student
{
public:
std::string lastname, firstname;
};
int main()
{
std::unique_ptr<Student> p = (2<3) ? std::make_unique<Student>() : nullptr;
if (p != nullptr)
std::cout << p->firstname << ' ' << p->lastname << std::endl;
return 0;
} // Student is automatically deleted when the unique_ptr p goes out of scope