Say I have:
class A
{
A()
{}
~A()
{}
};
class B
{
public:
B()
{}
~B()
{}
private:
static A mA;
};
B* pB = new B;
delete pB;
When I call delete pB, B's destructor will be called. Will this then call the destructor for static member A?
The keyword static means that the variable is independent of instances. That's why you can access static variables and methods without instantiating an object from the class in the first place. That's why destroying an instance will not affect any static variables.
Of course not. First of all, you've defined an explicit empty destructor. And if the default destructor did that, you could never destruct instances without risking making the class unusable.
C++ Standard 03, 9.4.2 Static data members:
A static data member is not part of
the subobjects of a class. There is
only one copy of a static data member
shared by all the objects of the
class.class.
A static data member is not part of the class -- hence it's not tied to the classes lifetime nor at construction or destruction.
Construction (9.4.2/3)
Once the static data member has been
defined, it exists even if no objects
of its class have been created.of its class have been created.
Destruction (9.4.2/7)
Static data members are initialized and destroyed exactly like non-local objects.
Objects with a static lifetime will be destructed when the application terminates. Among the various static objects that might be in the program, the destructors are called in the reverse order of how the objects were constructed.
The construction/destruction of object instances has no effect on when a static member is constructed or destroyed.
Static members do not live in the memory space assigned to an instance of the class. Therefore, it will not be deleted or deinitialized unless you do it explicitly in any part of your code (including the class destructor, but your code logic must handle the possibility of having multiple instances and so on...)
Static variables is also known as class variables. This is as opposed to instance variables. As these names implies, class variables pertain to the entire class, where as instance variables belong to an instance. One can derive the life span of these variables based on these facts.
Another way to look at this assume calling the destructor actually destroys static variables. Imagine then the consequence of one object gets instantiated and then gets deleted. What would happen the the static variables which are shared by all other objects of the class which are still being in used.
Related
I need a parent class to have a pointer to a child class' struct member. Is it possible to solve this during initialization as shown below, or will the address to _foo not be available/be invalid?
struct Foo { int a; int b; }
class A {
public:
A(void* fooHandle) : _fooHandle(fooHandle) {}
private:
void* _fooHandle;
};
class B : public A {
public:
B() : A(&_foo) {
/* _foo initialized here */
}
private:
Foo _foo;
};
Is this code safe? I.e. will &_foo give a valid address? Of course I mean according to the standard, not whether it may work for some compilers.
Yes, this is perfectly safe.
EDIT (explanation): The storage for the object is allocated before any constructor is called. Objects occupy a region of storage that has one start and one end address. There may be gaps inbetween (padding). However for the whole lifetime of an object, all it's members are alive as well. When the constructors are called (eventually) all member objects part of the class the constructor of which is called, already live (by constructor I mean the part between {…}). This is why, if you need initialization before constructor execution you have to provide initializers. Members are initialized in the order as it appears in the class and you'll get severe warnings if initializers appear in a different order, so as long as you pass addresses to members, which went through initialization, you're within the lifetime of these members.
In the same way the lifetime of members ends only after all destructors were called.
Of course anything created with new and destroyed with delete has lifetimes that are not tied to class instance lifetimes, so you've to be careful with that.
However I wonder what the practical application of this is. Also I'd suggest to use a reference instead of a pointer to enforce passing a valid object and also making the constructor protected, so that it can be used only from child classes.
Consider these two classes in C++11:
class A
{
ArbitraryClass someInstance;
};
class B : public A
{
};
And consider I use B as such:
B *foo = new B;
delete foo;
As I understand, the implicit destructor of A will not be called here.
Is someInstance still destroyed under these circumstances, because it becomes "associated" as a member of B? Or do I need to declare a virtual destructor on A to automatically trigger the member's destruction?
You need a virtual destructor in a delete expression's statically known class (in your case B) if that class is different from the most derived class of the object (in your case also B). In your case those classes are the same, so you don't need a virtual destructor: everything's destroyed properly. But if you had made the pointer type A*, then you'd need a virtual destructor in A to avoid Undefined Behavior (nasal daemons and such).
How do I ensure ...
Mostly by doing nothing.
As I understand, the implicit destructor of A will not be called here.
Wrong.
Is someInstance still destroyed under these circumstances
Yes.
because it becomes "associated" as a member of B?
Because it is a member of A, and A is destroyed.
Or do I need to declare a virtual destructor on A to automatically trigger the member's destruction?
Not in the case of the code you posted, but if (as is likely) you will be using polymorphism by deleting pointers to A that could be B or other subclasses of A you should give A a virtual destructor.
Someone told me that constructor creates the objects. But on internet I searched that constructor executed when objects created.. Can you explain about this? I'm new to C++
In C++ a constructor is a special kind of class member function that
is executed when an object of that class is instantiated.
Constructors are typically used to initialize member variables of the
class to appropriate default values, or to allow the user to easily
initialize those member variables to whatever values are desired.
So when you call the constructor you have an already instantiated object, so the constructor doesn't create the object, nor creates the objects variables, it is simply used to initialize the variables inside that object (or to make some task you want to before the object is used).
EDIT: Also:
A constructor performs its work in this order:
It calls base class and member constructors in the order of
declaration.
If the class is derived from virtual base classes, it
initializes the object's virtual base pointers.
If the class has or
inherits virtual functions, it initializes the object's virtual
function pointers. Virtual function pointers point to the class's
virtual function table to enable correct binding of virtual function
calls to code.
It executes any code in its function body.
Check these links for more infos:
http://www.learncpp.com/cpp-tutorial/85-constructors/
https://msdn.microsoft.com/en-us/library/s16xw1a8.aspx
https://isocpp.org/wiki/faq/ctors
class a{int a = 0;int b = 0;} a obj = new a();
in above code
your obj is created memory for obj is allocated in stack and then constructor
code is execute
Say I have a class and I have a static member in it, but I don't create any objects of that type. Will the memory be occupied for the static variable? If it would be occupied, what is the point of putting it in a class?
No.
Static members don't belong to the instances of class. They don't increase instances and class size even by 1 bit!
struct A
{
int i;
static int j;
};
struct B
{
int i;
};
std::cout << (sizeof(A) == sizeof(B)) << std::endl;
Output:
1
That is, size of A and B is exactly the same. Static members are more like global objects accessed through A::j.
See demonstration at ideone : http://www.ideone.com/YeYxe
$9.4.2/1 from the C++ Standard (2003),
A static data member is not part of
the subobjects of a class. There is
only one copy of a static data member
shared by all the objects of the
class.
$9.4.2/3 and 7 from the Standard,
once the static data member has been
defined, it exists even if no objects
of its class have been created.
Static data members are initialized
and destroyed exactly like non-local
objects (3.6.2, 3.6.3).
As I said, static members are more like global objects!
The C++ standard doesn't explicitly state when static memory is allocated, as long as it is available on first use. That said, it is most likely allocated during program initialization, thus guaranteeing its presence as soon as it is required, without needing special-case code to detect and perform allocation on access.
The purpose of putting static data into a class is the same as putting any other data into classes. By putting the data into a class structure, you are defining an encapsulating namespace, as well as being able to control access using accessor and mutator methods; this, in turn, will allow you to validate data going into the static memory store, and to ensure consistency throughout the use of this data.
Static variables are stored in a special memory area called BSS, while instances of a class are stored in a heap or on a stack. So, static members are stored separately.
Say I have a class and I have a static member in it, but I don't create any objects of that type. Will the memory be occupied for the static variable? If it would be occupied, what is the point of putting it in a class?
No.
Static members don't belong to the instances of class. They don't increase instances and class size even by 1 bit!
struct A
{
int i;
static int j;
};
struct B
{
int i;
};
std::cout << (sizeof(A) == sizeof(B)) << std::endl;
Output:
1
That is, size of A and B is exactly the same. Static members are more like global objects accessed through A::j.
See demonstration at ideone : http://www.ideone.com/YeYxe
$9.4.2/1 from the C++ Standard (2003),
A static data member is not part of
the subobjects of a class. There is
only one copy of a static data member
shared by all the objects of the
class.
$9.4.2/3 and 7 from the Standard,
once the static data member has been
defined, it exists even if no objects
of its class have been created.
Static data members are initialized
and destroyed exactly like non-local
objects (3.6.2, 3.6.3).
As I said, static members are more like global objects!
The C++ standard doesn't explicitly state when static memory is allocated, as long as it is available on first use. That said, it is most likely allocated during program initialization, thus guaranteeing its presence as soon as it is required, without needing special-case code to detect and perform allocation on access.
The purpose of putting static data into a class is the same as putting any other data into classes. By putting the data into a class structure, you are defining an encapsulating namespace, as well as being able to control access using accessor and mutator methods; this, in turn, will allow you to validate data going into the static memory store, and to ensure consistency throughout the use of this data.
Static variables are stored in a special memory area called BSS, while instances of a class are stored in a heap or on a stack. So, static members are stored separately.