5

I need create a string/vector. I know how long it should be, however, I'd like to write the right thing into it later. Can I create it with a specified length but without any initialization (neither explicit nor implicit), like what malloc does? Because I'll write into it properly before reading from it, it would be a waste of time to initialize it at construction.

I hoped I could write with arbitrary order after creating the vector, like

vector<int> v(10); // Some magic to create v with 10 of uninitialized ints
v[6] = 1;
v[3] = 2;
...

Seemingly that's impossible.

5
  • Possible duplicate of Choice between vector::resize() and vector::reserve() Commented May 19, 2016 at 8:23
  • can also use constructor with size_t. Commented May 19, 2016 at 8:32
  • 2
    @SHR, this will call the default constructor (if its implemented) Commented May 19, 2016 at 8:33
  • Could you use std::array? Commented May 19, 2016 at 10:28
  • @songyuanyao Thanks for your answer and comment. I think std::array would be good in the example I gave. However I could not use it in the real cases I met because string/vector was specified by the interface. Also, in some of the cases the size would be determined at run time instead of compile time. Commented May 20, 2016 at 2:25

6 Answers 6

8

Yes, you can, with boost::noinit_adaptor:

vector<int, boost::noinit_adaptor<std::allocator<int>> v(10);

Under the hood it redefines allocator::construct to do default initialization using new(p) T instead of value initialization new(p) T().

For built-in types default initialization does nothing, whereas value initialization zero-initializes.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the only exact answer to the question as calling .reserve() means having calls to .push_back() in order, whereas the OP seems to require random access to the container after non-initialized allocation.
7

If I understand your question properly, you want std::vector::reserve or std::basic_string::reserve.

std::vector<int> v;               // empty vector
v.reserve(how_long_it_should_be); // insure the capacity
v.push_back(the_right_thing);     // add elements
...

Edit for question's edit

vector<int> v(10);, will always construct v with 10 default-initialized int, i.e. 0. You might want std::array if you could know the size at compile time.

std::array<int, 10> v;  // construct v with 10 uninitialized int
v[6] = 1;
v[3] = 2;

LIVE

Comments

5

Using .reserve() on either containers will increase the .capacity() of the internal memory block allocated without calling any default constructors.

You can assert that the container has the right capacity at the moment you need it using .capacity(). Note that .size() will be different to .capacity() after a .reserve() as the first returns the number of actual objects inside the container, while the seconds returns the total number of objects the current memory block can handle without reallocation.

It is good practice (especially for std::vector) to empirically .reserve() your containers to avoid extra allocations at runtime. If you are using at least C++11, in case you want the remaining memory back and you can deal with some copying/moving, you can use shrink_to_fit().

Note that std::string::reserve differs from std::vector::reserve in case the new capacity requested is smaller than the current capacity. The string will take it as a non-binding request to shrink, while the vector will ignore the request.

Comments

1

When growing a vector, the new object must be initialized one way or another. It's not possible to create a vector of uninitialized int objects, for example.

The closest you could get would be to define a class with a data member and a default constructor that does not initialize that member, e.g.:

struct bar { int x; bar() {} };

// ...
std::vector<bar> vec(5);

Then vec ultimately contains 5 uninitialized int subobjects.

The reserve function allocates memory but does not increase the count of objects in the vector; it does not help with the problem that when you do eventually want an object in the vector you must initialize that object.

Comments

0

Use .resize(x) to change the actual number of elements.
* If .size() > x then elements will be destroyed, back first.
* If .size() < x new elements will be added using their default constructor.

Use .reserve(x) to have the vector allocate memory for x elements but not instantiate any (.size() will not change).
* If .size() < x no action will be taken, and the vector will be unaffected.

Comments

0

From C++11 you can use fill constructor: http://www.cplusplus.com/reference/vector/vector/vector/ (2) fill constructor Constructs a container with n elements. Each element is a copy of val (if provided). BTW: there is quite big difference between string and vector.

5 Comments

he wants to increase the capacity without initialization.
According to doc it is initialized if val is provided. Are you sure it will be initialized?
I am not the one who downvoted. OP wants to avoid initialization. He just wants to pre-allocate raw memory to avoid the cost of allocation when he adds data in his container.
@MarcinKajzler I think the default constructor will be called if val is not provided.
Initializing is not usually the expensive part of allocation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.