Constructors and Destructors in C++

el/2024/3/2 11:55:22


Constructors and Destructors in C++

By Andrei Milea

Constructor and Destructor Order

The process of creating and deleting objects in C++ is not a trivial task. Every time an instance of a  class is created the constructor method is called. The constructor has the same name as the class and it doesn't return any type, while the destructor's name it's defined in the same way, but with a '~' in front: 

class String
{public:String() //constructor with no arguments:str(NULL),size(0)
{}String(int size) //constructor with one argument:str(NULL),size(size){str = new char[size];
}~String() //destructor
{delete [] str;
};private:char *str;int size;}
Even if a class is not equipped with a constructor, the compiler will generate code for one, called theimplicit default constructor. This will typically call the default constructors for all class members, if the class is using virtual methods it is used toinitialize the pointer to the virtual table, and, in class hierarchies, it calls the constructors of the base classes. Both constructors in the above example use  initialization lists in order to initialize the members of the class. 

The construction order of the members is the order in which they are defined, and for this reason the same order should be preserved in the initialization list to avoid confusion. 

To master developing and debugging C++ applications, more insight is required regarding the way constructors and destructors work. Some problems arise when we are dealing with class hierarchies. Let's take a look at the following example where class B is inherited from class A:
class A
{public:A(int m,int n):m(m),n(n)
{cout<<"constructor A"<<m<<n;
{};private:int m;
int n;};class B : public A{public:B():b(5) //error : default constructor to initialize A is not found
{cout<<"constructor B"<<b;
{};private:int b;};int main()
{B x;
return 0;};
When we create an object of type B, the A part of the B object must be initialized and since we provide a constructor for class A, the compiler will not create an implicit default constructor.This code will fail to compile because there is no default constructor for class A to be called. To fix this we could provide a default constructor in class A or explicitly call the existing constructor of A in the initialization list of the B's constructor:
{cout<<"constructor B"<<b;
Notice that we needed to call the constructor of A before doing any initialization in B, since the order of construction starts with the base class and ends with the most derived class.

Never Use Virtual Methods in Constructors or Destructors

A side effect of this behavior is that you should avoid calling virtual functions in a class's constructor (or destructor). The problem is that if a base class makes a virtual function call implemented by the derived class, that function may be implemented in terms of members that have not yet been initialized (think of the pain that would cause!). C++ solves this problem by treating the object as if it were the type of the base class, during the base class constructor, but this defeats the whole purpose of calling a virtual function in a constructor. Destruction, by the way, works in the same way. If you're interested, Scott Meyers has a  very nice writeup of this principle taken from his book  Effective C++: 55 Specific Ways to Improve Your Programs and Designs . 

The destruction order in derived objects goes in exactly the reverse order of construction: first the destructors of the most derived classes are called and then the destructor of the base classes.

Virtual Destructors

To build an object the constructor must be of the same type as the object and because of this a constructor cannot be a virtual function.But the same thing does not apply to destructors. A destructor can be defined as virtual or even pure virtual. You would use a virtual destructor if you ever expect a derived class to be destroyed through a pointer to the base class. This will ensure that the destructor of the most derived classes will get called:
A* b1 = new B;
delete b1;
If A does not have a virtual destructor, deleting b1 through a pointer of type A will merely invoke A's destructor. To enforce the calling of B's destructor in this case we must have specified A's destructor as virtual:
virtual ~A();
It is a good idea to use a virtual destructor in any class that will be used as an  interface (i.e., that has any other virtual method). If your class has no virtual methods, you may not want to declare the destructor virtual because doing so will require the addition of a vtable pointer. 

The destructor is called every time an object goes out of scope or when explicitly deleted by the programmer(using operator delete). The order in which local objects are implicitly deleted when the scope they are defined ends is the reverse order of their creation:
void f()
{string a(.some text.);string b = a;string c;c = b;
At the end of function f the destructors of objects c, b, a (in this order) are called and the same memory is deallocated three times causing undefined and wrong behavior.  Deleting an object more than one time is a serious error. To avoid this issue, class string must be provided with a copy constructor and a copy assignment operator which will allocate storage and copy the members by values. The same order of construction/destruction applies for temporary objects that are used in expressions or passed as parameters by value. However, the programmer is usually not concerned with temporary objects since they are managed by the C++ compiler. 

Unlike local objects,  static objects are constructed only the first time their definition is reached and destroyed at the end of the program.


Detail about How VPTR and Virtual table works

原文地址&#xff1a; Assumption: machine is 32-bit . Here I am going to explain How Virtual table, Virtual pointer for Virtual functions are internall…

解决:No configuration found for the specified action

原文地址: 今天首次使用Struts2&#xff0c;配置一切正常&#xff0c;使用常用tag也正常&#xff0c;但是在使用<s:form>标记时&#xff0c;发现控制台总是输出警告信息&#xff0c; 警告信息内容如下&#xff1a; 警告: N…




原文地址&#xff1a; 通常struts2加载struts2常量的顺序如下: 1. struts-default.xml&#xff1a;该文件保存在struts2-core-2.0.6.jar文件中。 2. struts-plugin.xml&#xff1a;该文件保存在struts2-Xxx-2.0.6.jar等Struts2插件J…


从Spring手册中摘录的一段&#xff0c;有关依赖注入的例子 The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions: <bean id"exampleBean" clas…


原文地址&#xff1a; 打开Twitter的注册页面&#xff0c;;查看一下源码&#xff0c;你会看到一个很长的禁用口令列表&#xff08;见本文最下面&#xff09;&#xff0c;其中的某些口令的确很雷人…

使用库org.json 和 Gson 解析 JSON格式字符串

org.json库为JSON创始人编写的解析JSON的java库&#xff0c;Gson为Google为我们提供的解析JSON格式数据的库。有关库内容的的下载参见&#xff1a; 以下是两个简单的测试程序 使用Gson库&#xff1a; public class User {String username;String password;p…

Programs as Data: Function Pointers(函数指针)

原文链接&#xff1a; A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate beh…

Improved Type Inference in C++11: auto, decltype, and the new function declaration syntax

原文链接地址&#xff1a; Note: C11 is the now offical name for the next version of the C standard, previously known as C0x. C11 introduces several new handy-dandy type in…

C++0x: The future of C++

原文链接 What is C0x? C0x is the working name for the new standard for C, adding many language features that Ill cover in this series on C0x. Just days ago, a C0x draft was voted on and finalized, meaning…