views:

745

answers:

16

According to John C. Mitchell - Concepts in programming languages,

[...] Java guarantees that a constructor is called whenever an object is created. [...]

This is pointed as a Java peculiarity which makes it different from C++ in its behaviour. So I must argue that C++ in some cases does not call any constructor for a class even if an object for that class is created.

I think that this happens when inheritance occurs, but I cannot figure out an example for that case.

Do you know any example?

+3  A: 

In C++, when an object is instantiated, a constructor of that class must be called.

leiz
The only correct answer here, as far as I can see! Who the hell are these people???
anon
Not necessarily. For POD types, the implicit default constructor will not be called, even if you can call it yourself.
David Rodríguez - dribeas
@dribeas, I explicated mentioned "object". And if you call a POD type constructor explicitly, it will be called. eg. int a = int(); a will be initialized to 0.
leiz
Neil, my guess would be: Java people ;)
Georg Fritzsche
In C++, an `int` is an object. In Java, an `int` is not an Object.
Steve Jessop
If you see use the definition of *object as storage location* as opposed to *object as instance of a class*.
Georg Fritzsche
Which I do, because the question is about C++ objects, and this answer begins "In C++" :-)
Steve Jessop
@leiz: The question is whether the c++ language warrants that a constructor will be called when an instance is created, and it will not for POD types. `POD_type x;` will create a local variable of type `POD_type` and will not do any construction.
David Rodríguez - dribeas
@dribeas: I would say that the constructor is called but does nothing.
Martin York
@martin: this take us to C code. You don't pay for what you don't ask for, so no call is done. By the way, a constructor always do the same thing and the implicit defined constructor default initialize class attributes.
fnieto
+1  A: 

Java constructors can call another constructor of the same class. In C++ that is impossible. http://www.parashift.com/c++-faq-lite/ctors.html

POD's (plain old data types) are not initialized via constructors in C++:

struct SimpleClass {
    int m_nNumber;
    double m_fAnother;
};

SimpleClass simpleobj = { 0 }; 
SimpleClass simpleobj2 = { 1, 0.5 };

In both cases no constructor is called, not even a generated default constructor:

If however, SimpleClass itself defined a constructor, SimpleClass would not be a POD anymore and one of the constructors would always be called.

Sebastian
On the other hand, you cannot initialize instances of classes that have constructors with that syntax.
hrnt
And it doesn't address the question.
anon
POD do have constructor (implicit default constructor) it is just that the compiler will not call it automatically, but you can do it yourself: `void f( POD const int main() { f( POD() ); }` will create a temporary default constructed (all fields initialized to 0) and pass it to f. (Assuming POD is actually defined and a POD type :) )
David Rodríguez - dribeas
A: 

Only When you overload new operator funtion then constructor is not called (it used to avoid constructor calling), else its in standard that constructor is invoked when object is created.

void * operator new ( size_t size )
{

     void *p = malloc(size);

     if(p)
       return p; 
     else
        cout<<endl<<"mem alloc failed";
}

class X
{   

   int X;

};

int main()
{

       X *pX;

       pX = reinterpret_cast<X *>(operator new(sizeof(X)*5)); // no ctor called

}
Ashish
The example is really just allocating memory using operator new, and then cast to an object pointer. It is misleading IMO because it does not really count as creating an object.
leiz
Nothing to do with the question. You might just as well have said malloc( sizeof(X) *5).
anon
Also, you don't have to overload operator new to do that. You could use malloc to achieve the same effect.
leiz
ya leiz you are correct but i just want to say that default new operator allocates memory and calls ctors and you can override this behaviour by using operator new function which in turn just allocates memory.
Ashish
@unknown if you override new for a class you can make it do anything you want, including always returning NULL. This has nothing to do with object construction, however.
anon
A: 

What he means is in Java, constructor of the super class is always called. This is done by calling super(...), and if you omit this compiler will insert one for you. Only exception is one constructor calls another constructor. In that case other constructor should call super(...).

This automatic code insertion by the compiler is strange actually. And if you do not have super(...) call, and the parent class does not have a constructor with no parameter it will result in a compile error. (It is odd to have a compile error for something that is automatically inserted.)

C++ will not do this automatic insertion for you.

Szere Dyeri
Oh yes it will.
anon
It's too late for me to take back my upmod. Neil is correct.
Gunslinger47
+2  A: 

There are particular cases in C++ where a constructor will not be called. In particular for POD types the implicitly defined default constructor will not be called in some situations.

struct X {
   int x;
};
int main() {
   X x;        // implicit default constructor not called
               //    No guarantee in the value of x.x
   X x1 = X(); // creates a temporary, calls its default constructor
               //    and copies that into x1. x1.x is guaranteed to be 0
}

I don't quite remember the whole set of situations where that can happen, but I seem to recall that it was mostly in this case.

To further address the issue:

This is pointed as a Java peculiarity which makes it different from C++ in its behaviour. So I must argue that C++ in some cases does not call any constructor for a class even if an object for that class is created.

Yes, with POD types you can instantiate objects and no constructor will be called. And the reason is

This is of course done for compatibility with C.

(as Neil comments out)

I think that this happens when inheritance occurs, but I cannot figure out an example for that case.

This has nothing to do with inheritance, but with the type of object being instantiated.

David Rodríguez - dribeas
This is of course done for compatibility with C.
anon
And I think that your answer, while correct in itself, muddies the waters and does not address the basic question.
anon
I think it does address the fact: there are situations in C++ where the constructor is not called. Or did I miss the question? Maybe I should have been more clear in that this has nothing to do with inheritance?
David Rodríguez - dribeas
I think the OP was thinking mainly about user-defined constructors. And if one of those exist, it *will* be called. The compiler-generated ones for POD types are a bit of a special case no matter what.
jalf
+1. The question calls for examples where an object is created but no constructor is called. This is such an example. Not sure why Neil says it doesn't answer the question. Unless the basic question is, "is Java just way better than C++? lolz". In which case it should indeed be answered by Neil's observation that the author of the class can prevent this happening in C++.
Steve Jessop
Excuse me for this silly question: are POD considered objects, because for the OO paradigm I think they are not: at least they lack of abstraction and subtyping.
hoheinzollern
Yes. From 1.8 [intro.object]: An _object_ is a region of storage. This applies to POD-structs, basic types, class instances, etc., etc.
Charles Bailey
It's true though, that the definition of "object" for C++ doesn't quite match the general concept of objects used when considering OO in general. Anyway POD classes can be derived from, it's just the derived class is not POD. I don't think that classic abstract OO says every class must *be* a subtype, just that subtypes should be available. And POD classes do provide abstraction, they just don't enforce data hiding. So whether they're considered objects depends who you ask, but if you ask a C++ programmer then they are.
Steve Jessop
+3  A: 

For C++ types that declare constructors, it is not possible to create instances of those types without the use of a constructor. For example:

class A {
   public:
      A( int x ) : n( x ) {}
  private:
      int n;
};

it is not posible to create instancev of A without using the A(int) constructor, except by copying, which in this instance will use the synthesised copy constructor. In either case, a constructor must be used.

anon
A: 

As far as I remember, Meyers in his "Effective C++" says, that the object is ONLY created when the control flow has reached his constructor's end. Otherwise it is not an object. Whenever you want to mistreat some raw memory for an actual object, you can do this:

class SomeClass
{
   int Foo, int Bar;
};

SomeClass* createButNotConstruct()
{
   char * ptrMem = new char[ sizeof(SomeClass) ];
   return reinterpret_cast<SomeClass*>(ptrMem);
}

You won't hit any constructors here, but you may think, that you are operating a newly created object (and have a great time debugging it);

SadSido
You don't create a SomeClass, you just allocate some memory that happens to have the same size that a SomeCleass would have.
anon
You are right. I don't think I mention that I create a SomeClass object anywhere... If you read the entire answer, not only the code, of course...
SadSido
A: 

Trying to make things clear about C++. Lots of imprecise statements in answers.

In C++, a POD and a class behave the same way. A constructor is ALWAYS called. For POD, the default constructor does nothing: it does not initializes the value. But it is an error to say that no constructor is called.

Even with inheritance, constructors are called.

class A {
  public: A() {}
};

class B: public A {
  public: B() {}   // Even if not explicitely stated, class A constructor WILL be called!
};
Didier Trosset
Not really. `struct X { int x; }; void f( X const int main() { X x1; f( X() ); }` Instance `x1` is created and the constructor is not called. `f()` is called with a temporary for which the constructor is called. But maybe I am wrong, I had a hard time digesting that part of the standard...
David Rodríguez - dribeas
Yes, `struct X` constructor IS called for instance `x1`. But `struct X` constructor is a default constructor that does nothing.
Didier Trosset
+12  A: 

If your class defines at least one constructor, then the language will not allow you to construct an object of that type without calling a constructor.

If your class does not define a constructor, then the general rule is that the compiler-generated default constructor will be called.

As other posters have mentioned, if your class is a POD type, there are cases where your object will be left uninitialized. But this is not because the compiler "didn't call the constructor". It is because the type has no constructor (or it has one which does nothing), and is handled somewhat specially. But then again, POD types don't exist in Java, so that can't really be compared.

You can also hack around things so that the constructor is not called. For example, allocate a buffer of char's, take a pointer to the first char and cast it to the object type. Undefined behavior in most cases, of course, so it's not really "allowed", but the compiler generally won't complain.

But the bottom line is that any book which makes claims like these without being very explicit about which specific corner cases they're referring to, is most likely full of garbage. Then again, most people writing about C++ don't actually know much about the language, so it shouldn't be a surprise.

jalf
+1 for a clear and understandable answer.
Georg Fritzsche
I agree, and even in your 'hack around' description I wouldn't say that you'd have _created_ an object (unless the object has no, or a trivial constructor). While you've obtained storage for the object the object's lifetime doesn't begin until its constructor call has completed, and I'm not sure I'd agree with anyone who claimed that they had created an object if its lifetime hadn't begun.
Charles Bailey
@Charles: Yeah, definitely agreed. You haven't *created* an object. But you do have a pointer that you can use to pretend... Assuming you don't mind a truckload of undefined behavior. ;)
jalf
+1 for the "most people writing about C++". ;-)
DevSolar
+7  A: 

There are two cases in Java (I'm not aware of any more) in which a class' may be constructed without its constructor being called, without resulting to hacking in C or similar:

  • During deserialisation, serialisable classes do not have their constructor called. The no-arg constructor of the most derived non-serialisable class is invoked by the serialisation mechanism (in the Sun implementation, through non-verifiable bytecode).
  • When the evil Object.clone is used.

So the claim that constructors are always called in Java, is false.

Tom Hawtin - tackline
+1. I can confirm that. Seems Mr. Mitchell doesn't quite know what he is talking about.
meriton
I don't see what this answer has to do with C++.
anon
It's a qualified falsification of the quote.
Tom Hawtin - tackline
(Neil: I don't see what you answer has to do with Java...)
Tom Hawtin - tackline
I think the question asked rather clearly for the C++ behaviour.
Georg Fritzsche
The point is that the quote is wrong - there are situations in Java where an object is created without a constructor being called.
Jesper
In that case, the answer should make it clear that it is actually talking about Java, not C++. :)
jalf
A: 

This seems comes down to defining the term "object" so that the statement is a tautology. Specifically, with respect to Java, he's apparently defining "object" to mean an instance of a class. With respect to C++, he (apparently) uses a broader definition of object, that includes things like primitive types that don't even have constructors.

Regardless of his definitions, however, C++ and Java are much more alike than different in this respect. Both have primitive types that don't even have constructors. Both support creation of user defined types that guarantee the invocation of constructors when objects are created.

C++ does also support creation (within very specific limits) of user defined types that don't necessarily have constructors invoked under all possible circumstances. There are tight restrictions on this, however. One of them is that the constructor must be "trivial" -- i.e. it must be a constructor that does nothing that was automatically synthesized by the compiler.

In other words, if you write a class with a constructor, the compiler is guaranteed to use it at the right times (e.g. if you write a copy constructor, all copies will be made using your copy constructor). If you write a default constructor, the compiler will use it to make all objects of that type for which no initializer is supplied, and so on.

Jerry Coffin
A: 

In C++, the compiler will provide a default constructor if one is not provided. The constructor will allocate memory for members, if any, and other overhead (such as the stereotypical v-table).

When creating a class, if one of: constructor, copy constructor, assignment operator or destructor is written, the remaining three should also be written. The compiler can be prevented from creating default copy constructors and assignment operators by declaring them as protected or private and not providing a definition (implementation) of the method.

Thomas Matthews
This however does not address the problem: the fact that C++ produces implicit constructors does not imply that no constructor is called when a new object is instantiated, as the implicit constructor is called.
hoheinzollern
+2  A: 

Java can actually allocate objects without(!) calling any constructor.

If you browse the sources of ObjectInputStream you will find that it allocates the deserialized objects without calling any constructor.

The method which allows you to do so is not part of the public API, it is in a sun.* package. However, please don't tell me it is not part of the language because of that. What you can do with public API is put together the byte stream of a deserialized object, read it in and there you go with an instance of the object whose constructor was never called!

Adrian
A: 

even in the case we use statically allocated memory buffer for object creation , constructor is called.

can be seen in the following code snippet. i haven't seen any general case yet where constructor is not called, but then there is so much to be seen :)

include

using namespace std;

class Object

{

public:

Object();

~Object();

};

inline Object::Object()

{

cout << "Constructor\n";

};

inline Object::~Object()

{

cout << "Destructor\n";

};

int main()

{

char buffer[2 * sizeof(Object)];

Object *obj = new(buffer) Object; // placement new, 1st object

new(buffer + sizeof(Object)) Object; // placement new, 2nd object

// delete obj; // DON’T DO THIS

obj[0].~Object(); // destroy 1st object

obj[1].~Object(); // destroy 2nd object

}

ishan
+1  A: 

Giving an interpretation, I have a suggestion about why the author says that for Java, without looking for any corner cases which I think don't address really the problem: you could think for example that PODs are not objects.

The fact that C++ has unsafe type casts is much more well known. For example, using a simple mixture of C and C++, you could do this:

class A {
   int x;
public:
   A() : X(0) {}
   virtual void f() { x=x+1; }
   virtual int getX() { return x; }
};

int main() {
   A *a = (A *)malloc(sizeof(A));
   cout << a->getX();
   free(a);
}

This is a perfectly acceptable program in C++ and uses the unchecked form of type cast to avoid constructor invocation. In this case x is not initialized, so we might expect an unpredictable behaviour.

However, there might be other cases in which also Java fails to apply this rule, the mention of serialized object is perfectly reasonable and correct, even though you know for sure that the object has already been constructed in some way (unless you do some hacking on the serialized encoding of course).

hoheinzollern
A: 

In Java there are some situations when the constructor is not called.

For example when a class is deserialized, the default constructor of the first non-serializable class in the type hierarchy will be called, but not the constructor of the current class. Also Object.clone avoids calling the constructor. You can also generate bytecode and do it yourself.

To understand how this is possible, even without native code magic inside the JRE, just have a look at the Java bytecode. When the new keyword is used in Java code, two bytecode instructions are generated from it - first the instance is allocated with the new instruction and then the constructor is called with the invokespecial instruction.

If you generate your own bytecode (for example with ASM), it's possible change the invokespecial instruction to call the constructor of one of the actual type's super classes' constructor (such as java.lang.Object) or even completely skip calling the constructor. The JVM will not complain about it. (The bytecode verification only checks that each constructor calls its super class's constructor, but the caller of the constructor is not checked for which constructor is called after new.)

You can also use the Objenesis library for it, so you don't need to generate the bytecode manually.

Esko Luontola