1. Why is the constructor and destructor not returning a value?
Constructors and destructors are two very special functions: they have no return value. This is obviously different from a function that returns a void, although the latter does not return any values, but it also allows it to do something else, while constructors and destructors are not allowed. The behavior of creating and eliminating an object in a program is very special, like birth and death, and is always called by the compiler to ensure that they are executed. If they have a return value, either the compiler must know how to handle the return value, or the constructor and destructor can only be explicitly called by the client programmer itself, so that security is compromised. In addition, the destructor does not take any arguments, because the destructor does not require any options.
If the constructor is allowed to have a return value, in some cases it will cause ambiguity. Here are two examples of
Class C{public: C (): X (0) { } C (int i): x (i) { }private: int x;};
If the constructor of C can have a return value, such as Int:int C (): X (0) {return 1;}//1 indicates a construction success, 0 means failure
So what's going to happen with the code below?
c C = C (); At this time c.x = = 1!!!
Obviously, C () calls the parameterless constructor of C. The constructor returns an int value of 1. Exactly c has one but parameter constructor C (int i). So the chaos came. c C = C (), as specified in C + +, creates a temporary object with the default constructor and initializes C with this temporary object. At this point, the value of c.x should be 0. However, if C::C () has a return value and returns 1 (to indicate success), C + + uses 1 to initialize C, called but the parameter constructor c::c (int i). The resulting c.x will be 1. As a result, semantics produce ambiguity. Makes C + + already very complex syntax, further confusion.
The invocation of the constructor does not set the return value because of the particularity of the constructor. From the basic semantic point of view, the constructor should return the constructed object. Otherwise, we will not be able to use temporary objects:
void f (int a) {...} (1)
void f (const c& a) {...}//(2)
F (C ()); (3), who actually calls?
for (3), we want to call the (2), but if C::C () has the return value of type int, then whether it is a tune (1) Good or call (2) good. As a result, our overloaded systems, and even the entire grammatical system, will collapse.
The core here is the type of the expression. Currently, the type of expression C () is Class C. However, if C::C () has a return type R, then the type of the expression C () should be r, not C, and the above type problem will be raised.
2. Explicitly call constructors and destructors
#include <iostream>using namespace Std;class myclass{public: MyClass () { cout << " Constructors "<< Endl; } ~myclass () { cout << "destructors" << Endl; }}; int main () { myclass* pmyclass = new MyClass; Pmyclass->~myclass (); Delete Pmyclass; return 0;}
Results:
Constructors
Destructors//This is a destructor that shows the call
Destructors//This is a destructor for the delete call
What's the use of this? Sometimes it comes in handy to end the object's life cycle before it ends. Calling a destructor directly does not release the memory in which the object resides.
This is thought of:
New, actually did three things, one is: Call:: operator new allocates the required memory. The second is: Call the constructor. The third is: Returns a pointer to the newly allocated and constructed object.
When you delete, you do two things: Call the destructor, and two: call: operator Delete to free the memory.
So it is assumed that constructors can also be explicitly called. Do an experiment:
int main ()
{
myclass* Pmyclass = (myclass*) malloc (sizeof (MyClass));
Pmyclass->myclass ();
...
}
Error compiling Pmyclass->myclass ():
Error C2273: ' Function-style cast ': illegal as right side of ' operator '
It thought MyClass was this type.
There are two solutions:
First: Pmyclass->myclass::myclass ();
Second: New (Pmyclass) MyClass ();
The second usage involves the use of C + + placement new. Reference: http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html
What is the use of displaying the call constructor?
Sometimes, you might want to use malloc to allocate memory to class objects because of efficiency considerations, because malloc does not call constructors, so this time it will come in handy.
The following is also possible, although the built-in type has no constructors.
int* i = (int*) malloc (sizeof (int));
New (i) int ();
3. Copy (copy) constructor why cannot pass value
When you try to pass the copy constructor as a value, you will find that the compilation does not pass, and the error message is as follows:
Error:invalid constructor; You probably meant ' S (const s&) ' (roughly meaning: invalid constructor, you should write ... )
When compiling the wrong time you began to tangle, why copy constructor must be used to pass the reference, I surf the internet to find a lot of information, everyone's meaning is basically said if the value of the word can produce a dead loop. The compiler may not allow a copy constructor for value passing for such reasons, or it may be the C + + standard.
If this is the cause of the cycle of death, this should be the case:
Class S{public: s (int x): A (x) {} S (const S ST)//copy constructor { a = st.a; } Private: int A;}; int main () { S S1 (2); S S2 (S1); return 0;}
When the S2 is initialized to call the S2 copy constructor, because it is a value transfer, the system will re-request a space for the formal parameter St, and then call its own copy constructor to the value of the S1 data member to the St. When I call the copy constructor of itself and because it is a value pass, so ...
That is, whenever a copy constructor is called, a space is re-applied, and a copy constructor is invoked as soon as a space is re-applied, so that a dead loop is formed as it continues. So the copy constructor must not be a value pass.
4. Problems with constructors/destructors throwing exceptions
The constructor throws an exception:
1. It is not recommended to throw an exception in the constructor;
2. When the constructor throws an exception, the destructor will not be executed;
C + + can only delete the fully constructed object (fully contructed objects), and only one of the object's constructors is fully operational, and the object can be completely constructed. Each data member in the object should clean itself up, and if the constructor throws an exception, the object's destructor will not run. If your object needs to undo something that has already been done (such as allocating memory, opening a file, or locking a semaphore), the actions that need to be undone must be remembered by one of the data members inside the object.
destructor throws an exception:
Destructors are called in two cases. The first is to delete an object under normal circumstances, such as an object that is out of scope or explicitly deleted. The second is the exception-passing stack of Kaixie (stack-unwinding), which removes an object from the exception handling system.
In both of these cases, the exception may or may not be active when the destructor is called. Unfortunately, there is no way to differentiate between the two cases within the destructor. Therefore, you must conservatively assume that an exception is activated when you write the destructor, because if an exception is activated while the destructor throws an exception and causes the program control to be transferred outside the destructor, C + + calls the Terminate function. This function acts as the name indicates: it terminates your program and terminates immediately, even if the local object is not released.
Summarized as follows:
1. Destructors should not throw exceptions;
2. When there are some possible anomalies in the destructor, then it is necessary to encapsulate this possible exception completely inside the destructor and never let it throw out the function;
3. Do not throw an exception from the destructor during the process of handling another exception;
A good way to prevent resource leaks in constructors and destructors is to use smart Point (smart pointers), C + + STL provides class template auto_ptr, and instead of raw pointers with auto_ptr objects, you will no longer be concerned that the heap objects cannot be deleted, even when an exception is thrown. Objects can also be deleted in a timely manner. Because Auto_ptr's destructor uses a single-object form of delete instead of delete [], auto_ptr cannot be used to pointer to an array of objects. When copying a Auto_ptr object or assigning its value to another Auto_ptr object, the original Auto_ptr object is reset to the unbound state by transferring ownership of the underlying object from the original Auto_ptr object to the copy. Therefore, Auto_ptrs cannot be stored in the standard library container type. If you want to use a smart pointer as an element of an STL container, you can shared_ptr in the boost library.
Constructors and destructors