Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
564 views
in Technique[技术] by (71.8m points)

c++ - How can I have a pair with reference inside vector?

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 << "
";
}

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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_ptrs). 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...