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 **.
Related
Coming from Java, C++ is breaking my brain.
I need a class to hold a reference to a variable that's defined in the main scope because I need to modify that variable, but I won't be able to instantiate that class until some inner loop, and I also won't have the reference until then. This causes no end of challenges to my Java brain:
I'm used to declaring a variable to establish its scope, well in advance of knowing the actual value that will go in that variable. For example, creating a variable that will hold an object in my main scope like MyClass test; but C++ can't abide a vacuum and will use the default constructor to actually instantiate it right then and there.
Further, given that I want to pass a reference later on to that object (class), if I want the reference to be held as a member variable, it seems that the member variable must be initialized when it's declared. I can't just declare the member variable in my class definition and then use some MyClass::init(int &myreference){} later on to assign the reference when I'll have it in my program flow.
So this makes what I want to do seemingly impossible - pass a reference to a variable to be held as a member variable in the class at any other time than instantiation of that class. [UPDATE, in stack-overflow-rubber-ducking I realized that in this case I CAN actually know those variables ahead of time so can side-step all this mess. But the question I think is still pertinent as I'm sure I'll run into this pattern often]
Do I have no choice but to use pointers for this? Is there some obvious technique that my hours of Google-fu have been unable to unearth?
TLDR; - how to properly use references in class member variables when you can't define them at instantiation / constructor (ie: list initialization)?
Declare reference member variable that you won't have at instantiation
All references must be initialised. If you don't have anything to initialise it to, then you cannot have a reference.
The type that you seem to be looking for is a pointer. Like references, pointers are a form of indirection but unlike references, pointers can be default initialised, and they have a null state, and can made to point to an object after their initialisation.
Important note: Unlike Java references, C++ references and pointers do not generally extend the lifetime of the object that they refer to. It's very easy to unknowingly keep referring to an object outside of its lifetime, and attempting to access through such invalid reference will result in undefined behaviour. As such, if you do store a reference or a pointer to an object (that was provided as an argument) in a member, then you should make that absolutely clear to the caller who provides the object, so that they can ensure the correct lifetime. For example, you could name the class as something like reference_wrapper (which incidentally is a class that exists in the standard library).
In order to have semantics similar to Java references, you need to have shared ownership such that each owner extends the lifetime of the referred object. In C++, that can be achieved with a shared pointer (std::shared_ptr).
Note however, that it's generally best to not think in Java, and translate your Java thoughts into C++, but it's better to rather learn to think in C++. Shared ownership is convenient, but it has a cost and you have to consider whether you can afford it. A Java programmer must "unlearn" Java before they can write good C++. You can also subsitatute C++ and Java with most other programming languages and same will apply.
it seems that the member variable must be initialized when it's declared.
Member variables aren't directly initialised when they are declared. If you provide an initialiser in a member declaration, that is a default member initialiser which will be used if you don't provide an initialiser for that member in the member initialiser list of a constructor.
You can initialise a member reference to refer to an object provided as an argument in a (member initialiser list of a) constructor, but indeed not after the class instance has been initialised.
Reference member variables are even more problematic beyond the lifetime challenges that both references and pointers have. Since references cannot be made to point to other objects nor default initialised, such member necessarily makes the class non-"regular" i.e. the class won't behave similar ways as fundamental types do. This makes such classes less intuitive to use.
TL;DR:
Java idioms don't work in C++.
Java references are very different from C++ references.
If you think that you need a reference member, then take a step back and consider another idea. First thing to consider: Instead of referring to an object stored elsewhere, could the object be stored inside the class? Is the class needed in the first place?
What are the differences between declaring a variable in a header file as pointer or non-pointer? I am not sure if I understand the differences correctly.
E.g.
class MyClass {
private:
MyOtherClass* moc; // pointer
MyOtherClass moc2; // no pointer
}
So far I have come up with the following advantages/disadvantages when declaring a variable as pointer.
Advantages:
Lazy instantiation (no immediate creation of the object)
Variable lives on the heap which is much larger than the stack
Not only the default constructor can be used
Disadvantages:
Must be deleted manually in the destructor (btw. when is such a non-pointer variable destructed? When the program ends?)
What else is there to say?
Having an object signifies ownership. It's composition. Pointers can signify ownership, but most of the time they mean aggregation.
I.e. MyClass has a moc2 and uses moc.
Take your decision thinking about the design of the classes and how they interact with each other, not based on the pointer vs. object debate. Each MyClass object will have its own moc2 member, but multiple MyClass objects can share a moc between them.
Regarding your proposed advantages/disadvantages:
Advantages:
Lazy instantiation (no immediate creation of the object) - the pointer itself is initialized - remember your member is a pointer not an object. But I'll give you that you sometimes need this, although it's most of the time a code-smell.
Variable lives on the heap which is much larger than the stack - not necessarily - you can have a pointer to a stack-based variable as well. Also, if a MyClass object is allocated on the heap, so will moc2.
Not only the default constructor can be used - non-issue, you can use any constructor in both cases (see initialization-lists).
Disadvantages:
Must be deleted manually in the destructor (btw. when is such a non-pointer variable destructed? When the program ends?) - only if MyClass owns the member - it could be a pointer to some object created elsewhere, so MyClass isn't responsible for managing it.
Some of the advantages/disadvantages need correction, so here you go:
Advantages:
- Lazy instantiation (no immediate creation of the object)
- No need for the definition of the class to be visible, forward declaration suffices
Disadvantages:
- Must be deleted manually in the destructor
- You need to manually declare all copy constructors and assignment operators
- more complicated access (-> instead of .)
Some alternatives: smart pointer (std::unique_ptr). Has all advantages of the raw pointer and no need for explicit delete in the destructor, generally is much safer. Raw pointers should never be used unless really necessary, so if you need advantages of the pointer, use smart one.
And if you want lazy initialisation boost::optional may be used.
And in the end comments to your list:
Variable lives on the heap which is much larger than the stack
Not entirely true. If it is a pointer and object is created with new, the object will be in the heap. Otherwise it won't necessarily be on the stack. It will be where the parent object is. If the parent object is on the heap, the enclosed object - begin part of it - is on the heap also.
Not only the default constructor can be used
Not true at all, will initialisation list you can specify any arguments for member constructor.
Having a pointer does not automatically mean that you will have dynamically allocated variables. You can very much have a pointer to automatic or static variables as well (I'm not saying this is common or encouraged, I'm just being technical). Having a pointer gives you the option of allocating variables dynamically, but the downside is you have to manage the memory yourself, (See here and here).
As for when to use either, this has already been discussed on SO here
One difference that comes to mind is in header inclusions. When you have a pointer to an instance as a member, then you are permitted to forward-declare that type, whereas including it by value means that you have to include the header, which slows down build times.
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
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);