Yue Wang
Yue Wang

Reputation: 1750

While explicitly instantiating vector<someType>, what is the someType default constructor used for?

It's an exercise from C++ Primer 5th Edition:

Exercise 16.26: Assuming NoDefault is a class that does not have a default constructor, can we explicitly instantiate vector<NoDefault>? If not, why not? P.677

I know it doesn't compile if class NoDefault has no default constructor, but can not explain the reason. Can anyone tell me how is the default constructor used while explicitly instantiating template class std::vector<NoDefault> ?

Upvotes: 6

Views: 1805

Answers (3)

Shoe
Shoe

Reputation: 76280

While explicitly instantiating std::vector<someType>, what is the someType default constructor used for?

It's used to construct the elements of the array when resizing the std::vector. For example:

std::vector<T> vector(10);

will default construct 10 elements of type T.

Upvotes: 3

Steve Jessop
Steve Jessop

Reputation: 279315

C++11 introduces a new constructor, vector(size_type n), and "obviously" that constructor can't be instantiated unless the value_type is default-constructible. It was vector(size_type n, const T & = T(), const Allocator& alloc = Allocator()) in C++03, but they changed it to two separate constructors. A similar change was made to resize().

In GCC and as far as I know also per the standard: the vector template can be at least implicitly instantiated without the elements being default constructible. Implicit template class instantiation only instantiates the member functions you use.

In C++03 only the default arguments use default construction. You can explicitly instantiate the template, but you won't be able to call those functions without providing a value for that parameter.

So I'm pretty sure that change is what prevents vector<NoDefault> being explicitly instantiated in C++11 (and I suppose the allocator type needs to be default-constructible too). But I might have missed something. It seems a little odd to make that change given that it introduces this backward incompatibility. There's probably a proposal somewhere that justifies it if you want a deeper reason why this no longer works as opposed to just why this doesn't work :-)

Upvotes: 7

αλεχολυτ
αλεχολυτ

Reputation: 5039

As already said, the default constructor is required to create vector of objects. However, if one were to create a classic dynamic array (contiguous area of memory), it would be possible to address the lack of a default constructor using the placement new syntax:

#include <iostream>

struct Foo {
    explicit Foo(int a): a(a) {}
    int a;
};

int main() {
    void* mem = operator new[](10*sizeof(Foo));
    Foo* ptr = static_cast<Foo*>(mem);
    for (int i = 0; i < 10; ++i ) {
        new(&ptr[i])Foo(i);
        std::cout << ptr[i].a;
    }
    return 0;
}

Upvotes: 0

Related Questions