7

One of the std::vector constructors is stipulated as, emphasis mine:

explicit vector(size_type n, const Allocator& = Allocator());
Effects: Constructs a vector with n default-inserted elements using the specified allocator.
Requires: T shall be DefaultInsertable into *this.
Complexity: Linear in n.

Is default-insertion in any way related to default initialization? On this code:

std::vector<char> v(66000);

gcc 5.2 optimized produces:

  400d18:   bf d0 01 01 00          mov    $0x101d0,%edi
  400d1d:   48 83 c5 01             add    $0x1,%rbp
  400d21:   e8 1a fd ff ff          callq  400a40 <operator new(unsigned long)@plt>
  400d26:   31 f6                   xor    %esi,%esi
  400d28:   48 89 c3                mov    %rax,%rbx
  400d2b:   ba d0 01 01 00          mov    $0x101d0,%edx
  400d30:   48 89 c7                mov    %rax,%rdi
  400d33:   e8 38 fc ff ff          callq  400970 <memset@plt>

memset? What are you doing here? I thought this should simply do the equivalent of new char[66000]... that is, no initialization. clang 3.7 also emits a memset.

Why is there a memset here? Is this correct with respect to the standard? After all, if I wanted 66000 value-initialized chars I already have this constructor:

std::vector<char> v(66000, '\0');
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Isn't the value initialization part a property of the allocator? IIRC there is an answer (from Howard Hinnant I think) showing how to write a custom allocator to avoid initialization. – Praetorian Mar 09 '16 at 20:01
  • @Praetorian No clue. This wasn't the behavior I was expecting ex ante, or given the wording. Hence the question. – Barry Mar 09 '16 at 20:03
  • Since the question is about Why is there a memset here Maybe because C++ is a better C,meaning that most of C++ STL uses C in its libstc++ library – Joel Mar 09 '16 at 20:06
  • @Joel, what? C++ is a better C? – SergeyA Mar 09 '16 at 20:08
  • @SergeyA, from the book of Bjarne Stroustrup, not fully quoted, but says C++ is like a better C. – Joel Mar 09 '16 at 20:12
  • @Joel, to me it sounds like a quote from one of my relatives - 'sausages are better fish'. But than she doesn't like fish, and loves sausages. – SergeyA Mar 09 '16 at 20:15
  • Found [the answer](http://stackoverflow.com/a/21028912/241631) I was thinking of. So I guess if you really don't want initialization, use Casey's allocator. – Praetorian Mar 09 '16 at 20:16
  • @Praetorian Thanks! Seems questionable that this is the standard behavior. – Barry Mar 09 '16 at 20:23
  • That is standard behaviour, as my answer shows. – SergeyA Mar 09 '16 at 20:39
  • @SergeyA I'm not questioning that it *is* the standard behavior, rather whether it should be. – Barry Mar 09 '16 at 20:50
  • Than the question is 'should default allocator value-initialize objects it constructs'. Interesting question. I even wonder if this value-initialization is intentional or just a side-effect of empty parameter pack expansion. Totally possible that it is. – SergeyA Mar 09 '16 at 21:00
  • @SergeyA [So I thought I'd ask it](http://stackoverflow.com/q/35902965/2069064) – Barry Mar 09 '16 at 21:27

1 Answers1

13

This is correct behaviour. See 23.2.1:

An element of X is default-inserted if it is initialized by evaluation of the expression allocator_traits<A>::construct(m, p)

Than, allocator_traits<A>::construct will call a.construct(p, std::forward<Args>(args)...). Which, in turn, calls ::new((void *)p) U(std::forward<Args>(args)...), which in effect calls new(), which does value-initialization.

Conclusion:

memset() is appropriate.

Conclusion #2

Absent custom allocators, std::vector does not allow one an option to access uninitialized storage. Every object which is legitimately in vector was value-initialized.

Barry
  • 286,269
  • 29
  • 621
  • 977
SergeyA
  • 61,605
  • 5
  • 78
  • 137