Question

I mean, it's a matter of choosing words more than there is any difference between function and constructor call. The thing which is named "constructor of an object" can also be named "function with name object returning type object".

One could argue that C++ does not allow one to have the same function and type name; however, there is workaround to do that. C++ has special syntactic sugar (which is named a constructor) with which you can create a function with name object returning type object. So I think a constructor can be seen and used as a free standing function.

Are there some important semantic differences I am missing here?

Was it helpful?

Solution

A constructor is basically a method, yes, but it is a special method.

For example, in C++ a constructor isn't simply a function that returns a new instance of that type. If it was, inheritance wouldn't work. You couldn't call into the base constructors, because they'd return a new instance as well. You'd end up with a new instance of A, which is then returned to the constructor of B which creates a new instance of B, which is then returned to the constructor of C, etc.

Instead a constructor is more of an initialization method that is automatically called by the instance allocator. When you, say, call "new" to make an object on the heap, it allocates the memory for the type you asked for (using a memory allocator, like malloc), then calls the constructor method on it. The compiler has special rules for how, and in what order, that constructor can call the other constructors. For example, in C#, if you don't explicitly call a base constructor the compiler will add a call to the base default constructor.

It is those rules about how the compiler handles constructors that make it different from "a function named .ctor which returns an instance of the type".

OTHER TIPS

No, a constructor of object is very different from a function called object and returning object. A constructor has no name, but that is largely a technicality. The more important differences are that a constructor has no return type and that it cannot be called directly.

A constructor doesn't return anything because it is given a block of memory and operates on that memory in-place. It might help if you forget the name "constructor" for a moment and think of it as initialiser instead. The purpose of the constructor is not to construct an object "out of thin air." Its purpose is to initialise an object at the precise place in memory where it needs to be.

If a constructor was to return an object, that returned object (the return value) would have to live somewhere (probably on the stack), and there, it would need to be initialised somehow — we're running into a loop here.

This goes hand in hand with the fact that a constructor can never be called directly. If you have a class object and use an expression object() somewhere, it does not have the semantics of "call the constructor of object." It has the semantics of "create a temporary object of type object." The compiler translates this into allocating some place for the temporary to live in (probably/commonly on the stack), and calling the constructor to construct (= initialise) an object in that place.

The same principle applies when using new object(). This is a new-expression, which does two things:

  1. Call an allocation function operator new (which returns a void*) to allocate raw memory for the object.
  2. Issue a constructor call on this raw memory to construct (= initialise) an object in that piece of raw memory.

Thinking of a constructor of object as a function like this:

static object object();

is wrong. If anything, the way a constructor works is closer to this:

static void object(object &place_to_work_in);

With the exception that you can never call it directly. It is always only called when specified by a different language construct. Even placement new (also known as the "call a constructor here" trick), new (&place_for_object) object(), doesn't call the constructor directly. It translates into a call to the placement-new form of operator new which returns its argument, followed by a call to the constructor (just like any other new-expression).

Your attempt at rewording is incorrect.

Although a constructor looks like a member function with a name the same as the class' name, the fact is that a constructor doesn't really have a name at all. This is explicitly stated in the C++ standard (section [class.ctor]/1):

Constructors do not have names.

As far as: "I think a constructor can be seen and used as a free standing function" goes...well, I'm not quite sure what you mean. A free function certainly can't be a constructor--a constructor must be a member of a class. At the same time, you can certainly define a free function that creates an object and returns an instance of that object. That free function can even (sort of) have the same name as the type of object it creates, if you want to badly enough. For example, you could define the class inside a namespace, then define a function outside the namespace:

namespace foo { 
    class bar {};
}

foo::bar bar() { return foo::bar(); }

This isn't really the same name (the function is just bar and the class is foo::bar), but depending on your viewpoint, you could sort of look at them that way anyway.

Such a free function wouldn't have the other key characteristics of a constructor though. A constructor's invocation can be completely implicit. For example, if I have a class like:

class foo {
public:
   foo (int) {}
   foo operator+(foo const &other) {}
};

...then code like:

foo f(1);

foo h(0);
h = f + 1;

...can create a temporary foo object from the 1 so it can pass that foo object to foo::operator+. That simply won't happen with a free function, even if that free function were defined to take the right parameter type and return the required result type. For such an implicit conversion, a constructor is required.

I mean, it's a matter of choosing words more than there is any difference between function and constructor call. The thing which is named "constructor of an object" can also be named "function with name object returning type object".

First, constructors don't return anything and, as a consequence, do not have return types.

Second, constructors are different in that you cannot really call constructor directly in a way you call functions. Instead, if you declare a variable, appropriate constructors get called by the runtime.

Third, in case of inheritance, regular functions in subclasses override functions in parent classes. Constructors, on the other hand, cascade - parent class constructors are called first, then subclass constructors.

Fourth, constructors can have initialization lists, whereas "normal" function can't.

Licensed under: CC-BY-SA with attribution
scroll top