You are here:

C++/calling constructor explicitely

Advertisement


Question
hi Ralph ,

class sample
{
      int id;
      float sal;
public:
      sample()
      {
         cout<<"Sample created"<<endl;
      }
      ~sample()
      {
         cout<<"Sample Destroyed"<<endl;
      }
};
int main()
{
      {
         sample *s = new sample();
         sample();
      }
      cin.get();
      return 0;
}

In this program i am calling constructor explicitly...

so does sample created object created ..? how this memory get freed a d how we can access this object as i am not referencing it with any variable...

Thanks
Bhupal.

Answer
Well I am not sure what you mean when you say "so does sample created object created ..?" This I am afraid is a fairly meaningless phrase, but will run through what is going on in the hope I answer what you were asking about.

In the { } inner block of main, the first line:

   sample *s = new sample();

creates a new object of type sample dynamically on the free store and assigns a pointer to this object to the local variable s. The next line:

   sample();

creates a temporary sample object on the stack frame of the function call to main. As it is not assigned to anything it is destroyed at the end of the statement in which it is created in a similar manner to all automatic objects when they go out of scope.

Note that as s points to a dynamically allocated sample object and there is no delete s; statement the object pointed to by s is never properly destroyed, although desktop, workstation and server class operating systems will clean up a process' resources when it is destroyed so the raw memory used by the object pointed to by s will not be lost for reuse by the system for ever.

You might like to expand your experimental code something like so:

   int main()
   {
       {
         sample *s = new sample();
         cout << "After dynamic sample object creation, before temporary sample object creation" << std::endl;
         sample();
         cout << "After temporary sample object creation, before local sample object creation" << std::endl;
         sample ls;
         cout << "After local sample object creation, before closing of inner block" << std::endl;
       }
       cout << "After closing of inner block" << std::endl;
       cin.get();
       return 0;
   }

Here I have added a named local variable ls of type sample and added progress trace outputs after / before each point of interest. The output should look something like so:

   Sample created
   After dynamic sample object creation, before temporary sample object creation
   Sample created
   Sample Destroyed
   After temporary sample object creation, before local sample object creation
   Sample created
   After local sample object creation, before closing of inner block
   Sample Destroyed
   After closing of inner block

The first "Sample created" line is due to the dynamically created sample object whose pointer is assigned to s.

The second "Sample created" line is immediately followed by a "Sample destroyed" line and is due to creation and then immediate destruction of the temporary sample object.

The third "Sample created" line is due to the added local sample object. As can be seen it is destroyed at the closing of the inner block - as is the case for all local objects - they go out of scope at the end of the block they are defined in and are destroyed at this point, whether due to code execution normally ending the block or  due to an exception being thrown.

Note that s is also destroyed on the closing of the inner block but s is a pointer type and pointer types have do-nothing destructors. Specifically note that it is the _pointer_ that is destroyed and _not_ what it points to.

As the object pointed to by s is never destroyed (by an explicit delete) its destructor is never called so there is no third "Sample destroyed" line output.

And yes the temporary sample object cannot be accessed beyond the statement it is created on, but this does not mean it cannot be accessed:

   sample().some_instance_member_function_of_sample();

for example (assuming you add some_instance_member_function_of_sample as a public instance member function to sample), or we could use such temporary objects as function call arguments:

   function_taking_a_sample_by_value( sample() );
   function_taking_a_sample_by_reference_to_const( sample() );

or in other expressions. Note that we can pass a temporary object by value - as a copy will be made, or by reference to constant - as this implies the state of the argument is not modified. However we cannot pass a temporary by reference to a non-constant object as doing so implies that the state of the referenced object will be changed in the function call - and these changes would be lost and useless in the case of temporary object and confusing if such a temporary were created implicitly by the compiler for type conversion purposes as then it would not be clear from the code why the object passed did not receive the expected changes (because the compiler created temporary received them instead).

Of course, as hinted on above, such uses of temporary objects are usually more interesting if the type of the temporary object created can be constructed from one or more other objects or values. For example if you require an object of one type but have an object of some other type then if the required type has a single argument constructor that can accept an object of the type of the object we have then we can create (construct) a temporary object of the required type in order to convert the value we have to the required type. One example that crops up now and again with char values is if we want to display the numeric value of a char rather than the character it represents. If we just do something like so:

   char a('A');
   std::cout << a << std::endl;

then we just get A output and not the value that is used to represent A in the character set used (65 if it is an ASCII based character set as is the common case these days). To get the underlying numeric value used to represent A in the character set we need to convert the char to another, non-character, integer type - which we can do by constructing a temporary int (for example) from the char value and outputting this temporary int:

   std::cout << int(a) << std::endl; // or even std::cout << int('A') << std::endl;

In fact any class that has constructors that take a single argument might, as mentioned above, be used by the compiler to implicitly convert a value of one type to temporary objects of such class types if doing so will allow an expression or function parameter to be valid. That is the compiler _will_ use such single argument accepting constructors to create temporary objects for type conversion purposes if necessary. Obviously this is not always desirable or even sensible and in fact could create ambiguities by causing more function overloads to be equally valid causing unexpected compilation failures. In such cases where we do not wish such single argument accepting constructors to be used by the compiler for implicit creation of temporary objects we can mark the constructor as explicit:

   class HolderOfThings
   {
   
   // ...
   
   public:
   
   // ...
   

   // Mark constructor as explicit to prevent it being considered for implicitly
   // converting size_t integer values to (temporary) HolderOfThings objects:

       explicit HolderOfThings( size_t number_of_things_held ) /* ... */
   
   //...
   
   };

Hope this helps.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.