[ ... ]
That's entirely just a perspective, a point of view, a way of looking at
things. Many more people would say, "It's a member function whose name is
identical to that of the class."
The standard ($12.1/1) says: "Constructors do not have
names."
Victor's statement is clearly more than "just a
perspective" -- it's _fact_.
The "many more people" you mention would clearly just be
plain wrong.
This is NOT a distinction without a difference either --
it becomes quite important under some circumstances. For
one example, since a ctor does not have a name, it can
never be found during name lookup.
Does the Standard make a distinction between a "call" and an
"invocation"? If it does, I wasn't aware of it, but I'll be more than
happy to change my use of language from here on in if so.
The standard doesn't seem to try to distinguish between
"call" and "invoke", but it very clearly distinguishes
between calling a function, and taking some action that
will (indirectly) call the function to be called.
For example, in discussing how ctors are called, the
standard says: "...an explicit type conversion using the
functional notation (5.2.3) will cause a constructor to
be called to initialize an object."
Oh... I think I finally understand the crux of this argument -- are you
basing your stance on the distinction between a "call" and an
"invocation"?
No -- on the difference between directly calling
something, and taking an action that indirectly causes it
to be called.
You don't call a constructor -- ever. You can't. It
doesn't have a name, so there's no way for its name to be
looked up, so there's no way for you to call it.
Your example using placement new did have a some point --
it's certainly true that placement new comes closer to
isolating the ctor call itself from other things, most
obviously allocating memory for the object.
Nonetheless, you're still not calling the ctor -- you're
still just taking an action that indirectly causes the
ctor to be called. In reality, the compiler often has to
generate extra "stuff" associated with doing construction
over and above a call to the ctor itself.
Consider one obvious example:
struct Y {
int val;
Y(int init) :val(init) {}
virtual ~Y() { std::cout << "~Y\n"; }
};
struct A {
A() {}
virtual ~A() {}
};
strut Z {
int val;
Z(int init) :val(init) { throw 1; }
};
class X : public Y {
A a;
Z z;
X(int a, int b) : Y(a), z(b) {}
};
Now, when you attempt to construct an object of class X,
even using placement new, the compiler has to do _quite_
a bit more than just call X's ctor. It has to arrange for
the ctors for A, Z, Y and X to be called (in the correct
order). Since Z's ctor turns out to throw an exception,
it also has to include code to catch the exception and
invoke the destructors for A and Y as well, and then re-
thrown the exception.
To summarize: no, you don't a ctor -- ever. There are a
number of things you can do that will cause ctors to be
called, but it's always done indirectly. Depending on the
classes involved, chances are that constructing an object
involves _quite_ a bit more than just calling its
constructor -- and while placement new removes one of the
other things that otherwise happens, it can still leave
quite a bit more than has to be done.