简体   繁体   中英

Pair of vector constructors: initializer list vs explicit construction

I call the std::pair<vector<int>, int> constructor two ways:

  • passing in an initializer list
  • passing in an explicit vector (r-value).

For some reason, the initializer list version makes a copy (and destroys one).
Here is my minimal code sample:

auto dummy() {
    return pair<vector<int>, int>{ {1,2,3,4,5}, 1};
}

auto dummy1() {
    return pair<vector<int>, int>{ vector{1,2,3,4,5}, 1};
}

auto dummy2() {
    return optional<vector<int> > { {1,2,3,4,5} };
}

After checking the compiler explorer, I found that the initializer list dummy() version calls operator new twice, and delete once. This happens with neither the explicit construction version dummy1() nor a similar std::optional constructor in dummy2() . I wouldn't expect this behavior. Does anyone know why? I checked with clang as well.

The problem comes from std::pair constructors and template argument deduction / overload resolution:

pair( const T1& x, const T2& y ); // (1)

template< class U1, class U2 >
pair( U1&& x, U2&& y );           // (2)

Note that there is, at least, one "missing" constructor:

pair( T1&& x, T2&& y );           // (3)

When you use list-initialization for the first parameter, the selected constructor is not (2) (with U1 = std::initializer_list<int> ) but (1) 1 . Thus, you need to construct a temporary std::vector<int> , which is passed as a const -reference to (1) , which has to make a copy.

You can confirm empirically this by either:

  • creating your own pair with the third constructor mentioned above — in this case, (3) will be chosen, and the temporary vector will be moved;
  • explicitly constructing an std::initializer_list<int> while constructing the std::pair :
pair<vector<int>, int>{ std::initializer_list<int>{1,2,3,4,5}, 1 };

On the other hand std::optional as a single templated constructor:

template < class U = value_type >
constexpr optional( U&& value );

...but there is a default value for U , which makes this constructor a valid candidate for overload resolution.


1 When you call pair{ {1,2,3,4,5}, 1 } , U1 is in a non-deduced context within (2) [temp.deduct.type]#5.6 , so deduction fails, which why (1) is selected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM