1

So calloc calls on the OS to retrieve zeroed pages on the heap: https://stackoverflow.com/a/2688522/2642059

What about C++11's vector constructor that only takes a size_t and 0-initializes the values? Ask the OS for a zeroed page in the general case, or does it need to initialize it's self because the vector's elements may be a class with a default initializer, which defaults members to a non-zero value?

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 2
    The default constructor for each element is called, thus is definitely something more than calling just `calloc`. – 101010 May 20 '16 at 13:03
  • The `calloc` *can* ask the operating system for already zeroed pages, but if the operating system doesn't supports it it works like normal `malloc` followed by a `memset`. – Some programmer dude May 20 '16 at 13:03
  • 1
    @101010: That is true for the non-specialized `std::vector`, but an implementor can specialize `std::vector`. – MSalters May 20 '16 at 13:08
  • 1
    It's not specified by the standard, but when it comes to performance optimization, the implementation are usually free to do as they please, as long as it doesn't change the behaviour of the function. I guess an implementation could check for `std::is_trivially_default_constructible` and use `calloc` if it judges it performs better on their platform – KABoissonneault May 20 '16 at 13:15

1 Answers1

3

std::vector<T> is part of the implementation, which means we can only see the results, not necessarily the magic behind the scenes. Furthermore, the implementation itself may (partially) specialize std::vector<T> as long as the observable results stay the same.

However, that doesn't mean std::vector<int> can just ask the OS for zeroed memory. It still has to go through std::allocator and ::operator new, even if you replaced the latter.

Of course, by the laws of compiler magic, if the compiler knows that you didn't, it may still ask the OS directly. But the chief problem with that logic is separate compilation. When compiling A.cpp containing std::vector<int>, the compiler won't know that B.cpp contains ::operator new.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Can you elaborate on that last comment? What do you mean by B.cpp containing `::operator new`? – Jonathan Mee May 20 '16 at 13:26
  • Well, that problem can (in theory) be avoided with whole program optimization, and detecting a default `::new`. I have seen a number of optimizations that are only possible if we presume default `::new`, such as this one and eliminating allocations completely. Also, `vector` need not be actual c++ code (but it (almost?) always is) – Yakk - Adam Nevraumont May 20 '16 at 13:32
  • @JonathanMee: `::operator new` is special in that you can define it, but if you don't define it anywhere you will get a default implementation. Exactly how this works is a detail of the compiler/linker. – MSalters May 20 '16 at 13:33
  • So I just realized that I could have looked at the complexity section, which is called out as linear, so you're right, apart from compiler magic this will be done iteratively: http://en.cppreference.com/w/cpp/container/vector/vector#Complexity – Jonathan Mee May 20 '16 at 13:54
  • @JonathanMee Complexity guarantees are upper bounds, not tight bounds. – T.C. May 20 '16 at 21:00