Reputation: 270
I really need to make std::vector
of std::pair
with reference (&
) inside, but it breaks inside the function when I try to push_back
reference value. After debugging I discovered, that the address of reference is different from the address inside unique_ptr
(but the value is the same).
When I don't use (here the foo()) any function that insert into vector it's the value it refers to is correct, but the addresses still don't match.
#include <iostream>
#include <memory>
#include <iterator>
#include <string>
#include <vector>
void foo(std::vector<std::pair<const int&, int> >& vector,
std::unique_ptr<int>& ptr) {
vector.push_back(std::make_pair<const int&, int>(*ptr, 11));
}
int main() {
std::vector<std::pair<const int&, int> > v;
std::unique_ptr<int> i = std::make_unique<int>(1);
std::unique_ptr<int> b = std::make_unique<int>(0);
foo(v, i);
v.push_back(std::make_pair<const int&, int>(*b, 10));
std::cout << v.size() << ": ";
for (auto x : v) {
std::cout << x.first << ",";
}
std::cout << "\n";
}
This code demonstrates the problem - instead of "2: 1,0,"
it outputs "2: -342851272,0,"
(or similar big negative number in the first place).
Where is the problem?
Upvotes: 1
Views: 2272
Reputation: 320421
Since C++14 std::make_pair
is defined as
template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );
where V1
and V2
are std::decay<T1>::type
and std::decay<T2>::type
respectively.
This means that your make_pair<const int&, int>
calls do not really produce pairs with references as their first elements (contrary to what you apparently believed). They actually produce temporaries of pair<int, int>
type. At this point you lose any attachment to the original int
object stored in your unique_ptr
.
When you pass these pair<int, int>
temporaries to push_back
, they get implicitly converted to temporaries of pair<const int&, int>
type, which is your vector's element type. Through this mechanism you attach references inside your vector's element to int
members of those pair<int, int>
temporaries produced by make_pair
(not to int
objects stored in your unique_ptr
s). Once the temporaries expire, the references go sour.
In this case you can eliminate this specific problem by avoiding make_pair
altogether and simply directly constructing std::pair
objects of proper type, e.g.
vector.push_back(std::pair<const int&, int>(*ptr, 11));
but you might run into other problems caused by raw references later.
Upvotes: 3