We can declare a class member like this:
class Test {
public:
int a;
}
this is the how we declare, but I want to know where the variable a is defined.
I know the static class member, it is the static variable so it can't be defined in the class, it should be defined outside the class. So I think the normal class member should have a place to be defined, I guess it's the constructor where the normal member is defined implicitly. Is that right?
For non-static data members, the declaration and definition are one and the same.
So I think the normal class member should have a place to be defined, I guess it's the constructor where the normal member is defined implicitly.
I think I can see where you're coming from. For each static data members, there is only one variable instance per type (for templates - each template instantiation creates a distinct type) - and that's why the declaration is more like an extern declaration for normal variables - it's saying "this variable will have an address somewhere - ask the linker to stitch in the address later". The definition is where the program asks the compiler to reserve actual memory for the variable in that specific translation unit's object, which will be found by the linker and made accessible to the code in other translation units that knew of and access the variable based on the declaration. (It's a little more complicated for templates). So, loosely speaking and from a programmer perspective, the static data member definition appears to be the line of source code triggering the allocation of memory and arranging for the constructor to run. Once you've written the definition, allocation and construction are all sorted.
For non-static data members it's quite different though - when the class definition is parsed by the compiler there's still no actual request for those non-static data members to be given any memory anywhere, as there's not yet an instance object of that class type. Only when some other code indicates the need for an object instance will the compiler need to arrange memory (if not using placement new) and construction. Put another way, for non-static data-members definition and allocation/construction are generally decoupled - with separate source code.
This all applied recursively: when an object instance is itself static or of file/namespace scope, the memory and construction (including of the data members inside the class) will be arranged (not necessarily performed) when the definition is seen, as above. But very often object instances are on the stack or heap. Either way the allocation and construction code for the data members is driven by the way the containing object is created, and is unrelated to the data member's definition.
Every instance of an object is given some reserved space in memory for that object. Possibly in heap storage or on the stack.
It's at a specific location within that space that every member variable of that object is stored.
a could be defined right after the declaration, in the constructor, or completely outside of the class. Here is an example showing all the ways that a can be defined
class Test {
public:
int a = 5;
Test() {
a = 5;
}
};
int main() {
Test foo;
foo.a = 5;
return 0;
}
As a good practice, you should encapsulate your data members and manage their definitions in specific methods like SetA(), GetA(), and you can give default values in the constructor
Related
As far as my understanding all the member functions will be created in separate memory when class definition and is common for all objects. And only the member variables are created individually for each object. But how member function is executed when called using object?
Where is the address for these member function will be stored?
class B{
public:
int a;
void fun(){
}
};
int main(){
B b;
std::cout<<sizeof(b)<<std::endl;
}
If I execute this program, I get the output as 4(which is for only member variable). But calling b.fun() calls its member function correctly. How it is calling without storing its address within the object? Where the member function address are stored?
Is there anything like class memory layout where these addresses will be stored?
Non-virtual member functions are extremely like regular non-member functions, with the only difference between them being a pointer to the class instance passed as a very first argument upon invocation.
This is done automatically by compiler, so (in pseudo-code) your call b.fun() can be compiled into
B::Fun(&b);
Where B::Fun can be seen as a usual function. The address of this function does not have to stored in actual object (all objects of this class will use the same function), and thus size of the class does not include it.
Is there anything like class memory layout where these addresses will be stored?
There is for functions declared virtual, yes. In this case, the addresses of said functions are stored in a table and looked up at runtime. This in turn allows your code to dispatch to the correct function depending on the object's type when the function is called.
Non-virtual functions do not work this way. They're stored in the same way as free (i.e. non-member) functions, with the function name prefixed by the name of the class. No storage space within the object itself is required.
In both cases, a hidden this pointer is passed to the called function. This is what 'connects' it to your object.
so I am trying to work with multiple classes and objects for the first time.
Assuming I have sth like this
class control
{
public:
~control();
protected:
/*char* location*/
static node** adjacency_list;
};
I needed the adjacency_list pointer information to be available to all the derived class objects so I declared it as static (as advised in my previous question) in the base class.
My question is: When I define this variable as:
node** control::adjacency_list= new node[MAX];
in the source file, outside of my constructor, what is the real scope of adjacency_list?
Obviously the scope resolution operator is there, so I would assume that this variable is only available to the objects of this class and any other class that is derived from the control class. But reading about static vs global variable threads got me confused a little bit and I wanted to see if I am missing some information.
Also would my ~control() destructor be able to free the memory that is allocated with new in this instance?
You're actually using the term "scope" too broadly. Not everything that (you seem to) describe as scope is actually scope.
The scope is within the class control. Which is why use of the scope resolution operator (::) is used, and the full name of the static member is control::adjacency_list.
(Technically, there are other definitions of scope in computer science - I'm just using one that arguably makes most sense in C++).
Accessibility of the member is something distinct from scope, and affects what other functions or types can directly access control::adjacency_list (the class control itself, friends, derived classes and structs).
control::adjacency_list, since it has static storage duration, will exist until program termination (independently of how control::adjacency_list is initialised, or how its value is changed during program execution).
The lifetime of whatever control::adjacency_list points at is also distinct from scope (and distinct from the lifetime of control::adjacency_list itself) and will depend on how it is initialised. If you use operator new [] to do that, the lifetime will be to the corresponding operator delete [].
Unless you use specific logic to manage the lifetime of whatever control::adjacency_list points at, it is often not a good idea to release it in a destructor of control. However, there are techniques that can be useful (e.g. use reference counting of class control, and the destructor only releases control::adjacency_list when the last instance of control is destructed). That sort of decision depends on your requirements and design - there are no absolute answers.
Incidentally, your claimed method of initialisation can't be correct, since
node** control::adjacency_list= new node[MAX];
would not compile. The expression new node[MAX] (assuming MAX is an integral value) gives a result of type node *. That cannot be implicitly converted to a node **.
In C++ implementations, typically code is not stored (in any form) inside class instances. The code segment is not in the same memory space as objects and the like. This means that member functions are not "stored" inside class instances.
But when a question was asked about this, I got to wondering: to what extent, if at all, does the standard prohibit member functions being stored inside their encapsulating class, to the extent that instantiating the class makes a copy of those functions? Theoretically, could I make an implementation that worked this way? And could it even remotely abide by the common ABIs?
If, in C++, code were a first-class value, then the code for a member function would be simply a const static class member, and you would no more expect to find that in an instance than you would any other static data member. (§ 9.4.2: "A static data member is not part of the subobjects of a class.")
However, code is not considered a value, and furthermore you cannot even construct a pointer to a member function (although you can construct a "pointer to member", that is not really a pointer since it is not usable without a reference to an instance). That makes member function code different both from static data members and non-member functions, both of which allow the creation of free-standing pointers, which furthermore have equality guarantees which (more or less) preclude copying.
Class instances do contain a reference to virtual member functions (indirectly, in most implementations; the pointer is actually to a static vtable) which must be copied when a new instance is created. No requirement is made on the size of the reference, so in theory (as far as I know) there is nothing to stop an implementation from avoiding the indirections and storing the entire code anew for each instance of the class.
But there is an exception for standard-layout types, which is a subset of classes with no virtual member functions, expressed in § 9.12/18, which requires that two standard-layout types with identical initial members have identical layout for the initial members. Recalling that standard-layout objects must be simply copyable with memcpy (§3.9/3), must be contiguous in memory (§1.8/5), and must include their members in order (§9.12/13), this requirement makes it effectively impossible to include class-specific static data in any standard-layout object, which would include the code for member functions.
So I conclude that at least for standard-layout objects, the C++ standard does prohibit the storage of static data, including code for member functions, within the object representation.
The title basically says it all, i wonder when static members of a c++ class are initialized and when they go out of scope.
I need this for the following problem. I have many objects of a class Foo and each object needs access to a resource, encapsulated by another class Bar. Synchronization is not an issue, so i want all objects to share the same Bar instance.
I'm using a simple managed pointer for reference counting.
Can i do the following:
class Foo {
private:
static managed_pointer<Bar> staticBar;
public:
Foo() {
if(!staticBar)
staticBar = new Bar;
}
/*
* use staticBar in various non-static member functions
*/
};
managed_pointer<Bar> Foo::staticBar = NULL;
the managed_pointer staticBar should delete the Bar object as soon as it goes out of scope - but when does this happen? when the last instance of Foo is destructed? on application exit?
Thanks for your advice!
statics and globals are initialized right before the program starts (before main is called, the program actually starts before that) and go out of scope after main exits.
Exceptions - local statics (static variables declared inside functions) and unused template class staticmembers.
It has nothing to do with the number of instances.
The standard does not specify a precise order of initialization, it is implementation specific. They will be instantiated at the start of the program and deallocated at the end.
You have to be very careful with what you are doing, because if you have some other static objects that rely on this object to exist, it's UB. There is no telling in what order they will be initialized.
You could possibly look into something like boost::call_once to ensure it's initialized once, but I wouldn't rely on the order the statics are initialized.
For all I know, you code would work, but I've been bitten by the static initialization issue before so I wanted to warn you.
EDIT: Also in your code, when the managed_ptr will go out of scope (end of program), it will delete the memory allocated automatically. But you should not do anything non-trivial in Bar's destructor as you may trigger UB by calling into other free'd instances or even code that has been removed (as it happened to me once where a dynamic library had been removed). Essentially you are in a minefield, so watch out.
The first thing that pops out of your question is the common misconception that scope and lifetime are equivalent concepts. They are not. In some cases as with local variables, the lifetime is bound to a particular context, but that is not always the case.
A class static member variable has class scope (it is accessible anywhere in the program) and static lifetime, which means that it will be initialized in order with respect to the other static variables in the same translation unit, and in an undefined order with respect to other static variables in other translation units, before main (caveat: initialization need not be performed before the first statement in main, but it is guaranteed to be before the first odr-use of the variable).
Constructors build objects from dust.
This is a statement which I have been coming across many times,recently.
While initializing a built-in datatype variable, the variable also HAS to be "built from dust" . So, are there also constructors for built in types?
Also, how does the compiler treat a BUILT IN DATATYPE and a USER DEFINED CLASS differently, while creating instances for each?
I mean details regarding constructors, destructors etc.
This query on stack overflow is regarding the same and it has some pretty intresting details , most intresting one being what Bjarne said ... !
Do built-in types have default constructors?
Simply put, according to the C++ standard:
12.1 Constructors [class.ctor]
2. A constructor is used to initialize objects of its class type...
so no, built-in datatypes (assuming you're talking about things like ints and floats) do not have constructors because they are not class types. Class types are are specified as such:
9 Classes [class]
1. A class is a type. Its name becomes a class-name (9.1) within
its scope.
class-name:
identifier
template-id
Class-specifiers and elaborated-type-specifiers (7.1.5.3) are used
to make class-names. An object of a class consists of a (possibly
empty) sequence of members and base class objects.
class-specifier:
class-head { member-specification (opt) }
class-head:
class-key identifieropt base-clauseopt
class-key nested-name-specifier identifier base-clauseopt
class-key nested-name-specifieropt template-id base-clauseopt
class-key:
class
struct
union
And since the built-in types are not declared like that, they cannot be class types.
So how are instances of built-in types created? The general process of bringing built-in and class instances into existance is called initialization, for which there's a huge 8-page section in the C++ standard (8.5) that lays out in excruciating detail about it. Here's some of the rules you can find in section 8.5.
As already mentioned, built-in data types don't have constructors.
But you still can use construction-like initialization syntax, like in int i(3), or int i = int(). As far as I know that was introduced to language to better support generic programming, i.e. to be able to write
template <class T>
T f() { T t = T(); }
f(42);
While initializing a built-in datatype variable, the variable also HAS to be "built from dust" . So, are there also constructors for built in types?
Per request, I am rebuilding my answer from dust.
I'm not particularly fond of that "Constructors build objects from dust" phrase. It is a bit misleading.
An object, be it a primitive type, a pointer, or a instance of a big class, occupies a certain known amount of memory. That memory must somehow be set aside for the object. In some circumstances, that set-aside memory is initialized. That initialization is what constructors do. They do not set aside (or allocate) the memory needed to store the object. That step is performed before the constructor is called.
There are times when a variable does not have to be initialized. For example,
int some_function (int some argument) {
int index;
...
}
Note that index was not assigned a value. On entry to some_function, a chunk of memory is set aside for the variable index. This memory already exists somewhere; it is just set aside, or allocated. Since the memory already exists somewhere, each bit will have some pre-existing value. If a variable is not initialized, it will have an initial value. The initial value of the variable index might be 42, or 1404197501, or something entirely different.
Some languages provide a default initialization in case the programmer did not specify one. (C and C++ do not.) Sometimes there is nothing wrong with not initializing a variable to a known value. The very next statement might be an assignment statement, for example. The upside of providing a default initialization is that failing to initialize variables is a typical programming mistake. The downside is that this initialization has a cost, albeit typically tiny. That tiny cost can be significant when it occurs in a time-critical, multiply-nested loop. Not providing a default initial value fits the C and C++ philosophy of not providing something the programmer did not ask for.
Some variables, even non-class variables, absolutely do need to be given an initial value. For example, there is no way to assign a value to a variable that is of a reference type except in the declaration statement. The same goes for variables that are declared to be constant.
Some classes have hidden data that absolutely do need to be initialized. Some classes have const or reference data members that absolutely do need to be initialized. These classes need to be initialized, or constructed. Not all classes do need to be initialized. A class or structure that doesn't have any virtual functions, doesn't have an explicitly-provided constructor or destructor, and whose member data are all primitive data types, is called plain old data, or POD. POD classes do not need to be constructed.
Bottom line:
An object, whether it is a primitive type or an instance of a very complex class, is not "built from dust". Dust is, after all, very harmful to computers. They are built from bits.
Setting aside, or allocating, memory for some object and initializing that set-aside memory are two different things.
The memory need to store an object is allocated, not created. The memory already exists. Because that memory already exists, the bits that comprise the object will have some pre-existing values. You should of course never rely on those preexisting values, but they are there.
The reason for initializing variables, or data members, is to give them a reliable, known value. Sometimes that initialization is just a waste of CPU time. If you didn't ask the compiler to provide such a value, C and C++ assume the omission is intentional.
The constructor for some object does not allocate the memory needed to store the object itself. That step has already been done by the time the constructor is called. What a constructor does do is to initialize that already allocated memory.
The initial response:
A variable of a primitive type does not have to be "built from dust". The memory to store the variable needs to be allocated, but the variable can be left uninitialized. A constructor does not build the object from dust. A constructor does not allocate the memory needed to store the to-be constructed object. That memory has already been allocated by the time the constructor is called. (A constructor might initialize some pointer data member to memory allocated by the constructor, but the bits occupied by that pointer must already exist.)
Some objects such as primitive types and POD classes do not necessarily need to be initialized. Declare a non-static primitive type variable without an initial value and that variable will be uninitialized. The same goes for POD classes. Suppose you know you are going to assign a value to some variable before the value of the variable is accessed. Do you need to provide an initial value? No.
Some languages do give an initial value to every variable. C and C++ do not. If you didn't ask for an initial value, C and C++ are not going to force an initial value on the variable. That initialization has a cost, typically tiny, but it exists.
Built In data types(fundamental types, arrays,references, pointers, and enums) do not have constructors.
A constructor is a member function. A member function can only be defined for a class type
C++03 9.3/1:
"Functions declared in the definition of a class, excluding those declared with a friend specifier, are called member functions of that class".
Many a times usage of an POD type in certain syntax's(given below) might give an impression that they are constructed using constructors or copy constructors but it just Initialization without any of the two.
int x(5);