48

After writing:

std::pair<int, int> x;

Am I guaranteed that x.first and x.second are both zero? Or could they have any value?

The reason why I care is because I'm trying to determine whether a map whose values are pointers is guaranteed to return NULL if I access an element that's not in the map. I.e., if I do:

std::map<int, void*> my_map;
std::cout << int(my_map[5]) << std::endl;

then am I guaranteed to get zero (NULL)? Or is the behavior undefined?

Edward Loper
  • 15,374
  • 7
  • 43
  • 52

3 Answers3

43

Yes, that guarantee holds true. Quoting the C++11 standard, §20.3.2/2-3:

        constexpr pair();

2 Requires: is_default_constructible<first_type>::value is true and is_default_constructible<second_type>::value is true.
3 Effects: Value-initializes first and second.

And §8.5/7:

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type with a user-provided constructor, then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is non-trivial, that constructor is called.
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized.

And lastly, §8.5/5:

To zero-initialize an object or reference of type T means:

  • if T is a scalar type, the object is set to the value 0 (zero), taken as an integral constant expression, converted to T;
  • if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
  • if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-initialized and padding is initialized to zero bits;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.
ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • The default constructor of int is to set it to zero? – André Puel Jan 26 '12 at 21:58
  • 8
    @André : `int` doesn't have a default constructor, and default-initializing an `int` would leave its value undefined. What's being used here is _value-initialization_. – ildjarn Jan 26 '12 at 21:59
6

From C++11 standard, section § 20.3.2

constexpr pair();
...
Effects: Value-initializes first and second.

So it is well-defined that the default initialization of an std::pair<int, int> object will result in both members being set to 0.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
4

Yes, they are zero-initialized. A citation of Bjarne Stroustrup's "The C++ Programming Language" (3rd edn, Ch. 17.4.1.7):

The result of m[k] is equivalent to the result of (*(m.insert(make_pair(k,V())).first)).second, where V() is the default value of the mapped type. When you understand that equivalence, you probably understand associative containers.

For standard citations what default-initialized means look at the others answers.

René Richter
  • 3,839
  • 3
  • 34
  • 42
  • That citation seems to pertain to the behavior of `std::map<>::operator[]`, not to the behavior of default-constructing a `std::pair<>`. – ildjarn Jan 26 '12 at 22:06
  • @ildjarn: Correct. In Stroustrup's text `m` is a `std::map`. The pair is build and inserted to the map when accessing a non-existing key, like done in the second part of the OP's question. – René Richter Jan 26 '12 at 22:18
  • Ah, somehow I entirely overlooked the OP's use of `std::map<>`. +1 for paying attention. :-P – ildjarn Jan 26 '12 at 22:23
  • 1
    IMHO there is a typo—`m[k]` is equivalent to `m.insert(std::make_pair(k, V())).first->second`. – Eli4ph Jul 29 '18 at 12:37
  • 1
    @Eli4ph: Indeed the German edition left out a pair of parentheses, leading to syntac error. The English book version has it syntactically correct. Thanks! – René Richter Jul 30 '18 at 10:03