As I know std::allocator<T>::construct
takes only two parameters on older version of C++; the first is a pointer to raw, un-constructed memory in which we want to construct an object of type T
and the second one is a value of element type to initialize that object. So the copy-constructor is invoked:
struct Foo {
Foo(int, int) { cout << "Foo(int, int)" << endl; }
/*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};
int main(int argc, char* argv[]) {
allocator<Foo> a;
Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
// Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98
a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
a.construct(p, 10);// works on both
a.destroy(p);
a.destroy(p + 1);
a.deallocate(p, 200);
std::cout << std::endl;
}
Why on C++98 a.construct(p, 10)
calling the copy constructor but on C++11 and above is calling just the constructor that takes an integer?
Does this mean on C++ 11 because of some Copy-elision optimization even if the constructor Foo(int)
is explicit
works on such call: a.construct(p, 5)
works on C++11 even the constructor is explicit
what I am sure of is it doesn't works on C++98 if Foo(int)
is explicit
.
If so then if I compile that statement with some sort of disabling copy-elision
optimization will cause the compiler fail? Thank you.
This is because the declaration of construct
changed in C++11:
void construct( pointer p, const_reference val ); (1) (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args ); (2) (since C++11)
The first declaration calls the copy constructor, while the second declaration calls a constructor that matches the given list of arguments. This could be the copy constructor, but also another constructor as you saw in your code.
a.construct(p, 10)
calls the copy constructor in C++98 because the 10
is implicitly converted to Foo
via the Foo(int)
constructor. This conversion is not necessary in C++11 since there is a matching constructor that takes an int
(exactly the constructor that was used for converting in C++98). This is also the reason why the code doesn't work in C++98 when you add explicit
– it cannot convert the 10
to a Foo
then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With