如果我需要使用引用,有什么替代方法,而我传递的数据我无法更改类型,因此我无法真正存储指向它的指针?
#include <map>
#include<iostream>
#include<string>
using namespace std;
int main()
{
string test;
pair<string, string> p=pair<string, string>("Foo","Bar");
map<pair<string, string>, string&> m;
m[make_pair("aa","bb")]=test;
return 0;
}
$ g ++ MapPair.cpp /usr/include/c++/3.2.3/bits/stl_map.h: 在实例化
std::map<std::pair<std::string, std::string>, std::string&, std::less<std::pair<std::string, std::string> >, std::allocator<std::pair<const std::pair<std::string, std::string>, std::string&> > >': MapPair.cpp:15:
的std :: string&安培;” MapPair.cpp:In function
instantiated from here /usr/include/c++/3.2.3/bits/stl_map.h:221: forming reference to reference typeint main()': MapPair.cpp:16: no match for
std :: map,std :: string&amp ;, std :: less&gt;,
的std ::分配器,
的std :: string&安培;&GT; &GT; &GT;&安培; [std :: pair]'运算符 /usr/include/c++/3.2.3/bits/stl_pair.h: 在全球范围内: /usr/include/c++/3.2.3/bits/stl_pair.h: 在std::pair<const std::pair<std::string, std::string>, std::string&>': /usr/include/c++/3.2.3/bits/stl_tree.h:122: instantiated from
std :: _ Rb_tree_node的实例化中
我做错了什么导致这种错误?
答案 0 :(得分:33)
您无法存储参考文献。引用只是aliases to another variable。
地图需要存储字符串的副本:
map<pair<string, string>, string> m;
你得到那个特定错误的原因是因为地图中的某个地方,它将在mapped_type
上进行操作,在你的情况下是string&
。其中一项操作(例如operator[]
中的操作)将返回对mapped_type
的引用:
mapped_type& operator[](const key_type&)
与您的mapped_type
一起,将是:
string&& operator[](const key_type& _Keyval)
你不能引用参考文献:
标准8.3.4:
不应引用引用,不引用引用数组,也不引用引用指针。
在旁注中,我建议您使用typedef
,以便您的代码更易于阅读:
int main()
{
typedef pair<string, string> StringPair;
typedef map<StringPair, string> StringPairMap;
string test;
StringPair p("Foo","Bar");
StringPairMap m;
m[make_pair("aa","bb")] = test;
return 0;
}
答案 1 :(得分:20)
此前的答案已过时。今天我们将std::reference_wrapper
作为C ++ 11标准的一部分:
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string test;
pair<string, string> p = pair<string, string>("Foo", "Bar");
map<pair<string, string>, reference_wrapper<string>> m;
m[make_pair("aa", "bb")] = test;
return 0;
}
std :: reference_wrapper将隐式转换为对其内部类型的引用,但这在某些上下文中不起作用,在这种情况下,您可以调用.get()
进行访问。
http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
答案 2 :(得分:9)
您可以使用boost :: reference_wrapper在STL容器中存储引用。以下是您修改的示例(未经过测试,绝对写得不是很好,只是说明了一点)
#include <map>
#include<iostream>
#include<string>
#include <boost/ref.hpp>
int main()
{
typedef std::pair< std::string, std::string> PairType;
typedef std::map< PairType, boost::reference_wrapper<std::string> > MapType;
std::string test = "Hello there!!";
MapType m;
PairType pp = std::make_pair("aa","bb");
m.insert(std::make_pair(pp , boost::ref(test) ) );
MapType::iterator it (m.find( pp ) );
if(it != m.end())
{
std::cout << it->second.get() << std::endl;
}
//change test
test = "I am different now";
std::cout << it->second.get() << std::endl;
return 0;
}
答案 3 :(得分:2)
由于模板的构建方式,您无法使用引用作为val。你也可以改用指针。
答案 4 :(得分:1)
基本上,问题是,如果你可以在容器中使用引用。当然,你可以 IF 为你的容器准备好你的课程和。我在下面用两个简单的向量容器演示它:std::vector<>
修改vec
,另一个#include <iostream>
#include <vector>
// requires compilation with --std=c++11 (at least)
using namespace std;
class A {
int _a; // this is our true data
A *_p; // this is to cheat the compiler
public:
A(int n = 0) : _a(n), _p(0)
{ cout << "A constructor (" << this << "," << _a << ")\n"; }
// constructor used by the initializer_list (cheating the compiler)
A(const A& r) : _p(const_cast<A *>(&r))
{ cout << "A copy constructor (" << this << "<-" << &r << ")\n"; }
void print() const {cout << "A instance: " << this << "," << _a << "\n";}
~A() {cout << "A(" << this << "," << _a << ") destructor.\n";}
// just to see what is copied implicitly
A& operator=(const A& r) {
cout << "A instance copied (" << this << "," << _a << ")\n";
_a = r._a; _p = r._p;
return *this;
}
// just in case you want to check if instance is pure or fake
bool is_fake() const {return _p != 0;}
A *ptr() const {return _p;}
};
template<typename T, int sz>
class vec { // vector class using initializer_list of A-references!!
public:
const T *a[sz]; // store as pointers, retrieve as references
// because asignment to a reference causes copy operator to be invoked
int cur;
vec() : cur(0) {}
vec(std::initializer_list<T> l) : cur(0) {
cout << "construct using initializer list.\n";
for (auto& t : l) // expecting fake elements
a[cur++] = t.ptr();
}
const T& operator[](int i) {return *a[i];}
// expecting pure elements
vec& push_back(const T& r) {a[cur++] = &r; return *this;}
void copy_from(vec&& r) {
for (int i = 0; i < r.cur; ++i)
push_back(r[i]);
}
};
template<typename T>
class vectoref : public vector<T *> { // similar to vec but extending std::vector<>
using size_type = typename vector<T*>::size_type;
public:
vectoref() {}
vectoref(std::initializer_list<T> l) {
cout << "construct using initializer list.\n";
for (auto& t : l) // expecting fake elements
vector<T*>::push_back(t.ptr());
}
const T& operator[](size_type i) {return *vector<T*>::at(i);}
// expecting pure elements
vectoref& push_back(const T& r)
{ vector<T*>::push_back(&r); return *this; }
void copy_from(const vectoref&& r) {
for (size_type i = 0; i < r.size(); ++i)
vectoref<T>::push_back(r[i]);
}
};
class X { // user of initializer_list of A
public:
X() {}
void f(initializer_list<A> l) const {
cout << "In f({...}):\n";
for (auto& a : l)
a.ptr()->print();
}
};
int main()
{
A a(7), b(24), c(80);
cout << "----------------------------------\n";
vectoref<A> w{a,a,b,c}; // alternatively, use next line
// vec<A,5> w{a,a,b,c}; // 5-th element undefined
w[0].print();
w[3].print();
cout << "----------------------------------\n";
X x;
x.f({a,b,c,a,b,c,b,a});
cout << "==================================\n";
return 0;
}
从头开始实现。
{{1}}