为什么我在“形成对引用类型的引用”时出现错误 地图?

发布于 2024-07-27 13:33:27 字数 1569 浏览 2 评论 0 原文

如果我需要使用引用,并且我传递的数据无法更改其类型,因此我无法真正存储指向它的指针,那么替代方案是什么?

代码:

    #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::string&, std::less >, std::allocator, std::string> > >':MapPair.cpp:15:
从这里实例化 /usr/include/c++/3.2.3/bits/stl_map.h:221: 形成对引用类型的引用
std::string&' MapPair.cpp:在 函数int main()':MapPair.cpp:16: 不匹配 std::map、std::string&、 std::less >,
std::分配器,
std::string> > >& [std::pair]' 运算符 /usr/include/c++/3.2.3/bits/stl_pair.h: 在全球范围内: /usr/include/c++/3.2.3/bits/stl_pair.h: 在 std::pair, std::string>': /usr/include/c++/3.2.3/bits/stl_tree.h:122: 实例化自 std::_Rb_tree_node

我做错了什么导致这个错误?

What is the alternative if I need to use a reference, and the data I am passing I cannot change the type of, hence I cannot really store a pointer to it?

Code:

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

Error:

$ g++ MapPair.cpp
/usr/include/c++/3.2.3/bits/stl_map.h:
In instantiation of
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:
instantiated from here
/usr/include/c++/3.2.3/bits/stl_map.h:221:
forming reference to reference type
std::string&' MapPair.cpp: In
function int main()': MapPair.cpp:16:
no match for
std::map, std::string&,
std::less >,
std::allocator,
std::string&> > >& [std::pair]' operator
/usr/include/c++/3.2.3/bits/stl_pair.h:
At global scope:
/usr/include/c++/3.2.3/bits/stl_pair.h:
In instantiation of 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

What am I doing wrong to cause this errror?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ぃ弥猫深巷。 2024-08-03 13:33:27

您无法存储引用。 引用只是另一个变量的别名

地图需要存储字符串的副本:

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;

}

You cannot store references. References are just aliases to another variable.

The map needs a copy of the string to store:

map<pair<string, string>, string> m;

The reason you are getting that particular error is because somewhere in map, it's going to do an operation on the mapped_type which in your case is string&. One of those operations (like in operator[], for example) will return a reference to the mapped_type:

mapped_type& operator[](const key_type&)

Which, with your mapped_type, would be:

string&& operator[](const key_type& _Keyval)

And you cannot have a reference to a reference:

Standard 8.3.4:

There shall be no references to references, no arrays of references, and no pointers to references.


On a side note, I would recommend you use typedef's so your code is easier to read:

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;

}

久随 2024-08-03 13:33:27

这里以前的答案已经过时了。 今天,我们将 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() 进行访问。

The previous answers here are outdated. Today we have std::reference_wrapper as part of the C++11 standard:

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

A std::reference_wrapper will convert implicitly to a reference to its internal type, but this doesn't work in some contexts, in which case you call .get() for access.

http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

深居我梦 2024-08-03 13:33:27

您可以使用 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;
}

You can use boost::reference_wrapper to store references in STL containers. Here is your example modified (not tested, and definitely not very well written, just illustrates a point)

#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;
}
旧夏天 2024-08-03 13:33:27

由于模板的构建方式,您不能使用引用作为 val。 您也可以使用指针代替。

You cannot use references as the val, due to how the template is built. You could also use pointer instead.

香草可樂 2024-08-03 13:33:27

本质上,问题是是否可以在容器中使用引用。 当然,您可以,如果您正确准备了您的课程您的容器。 下面我用两个简单的向量容器进行演示:vectoref,它修改 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;
}

Essentially, the question is if you can use references in containers. Of course, you can, IF you properly prepare your class AND your container. I demonstrate it below with two simple vector containers: vectoref which modifies std::vector<> and the other, vec, which is implemented from scratch.

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文