为什么我不能制作参考文献?

时间:2009-05-28 18:04:10

标签: c++ vector reference stl containers

当我这样做时:

std::vector<int> hello;

一切都很好。但是,当我把它作为引用的向量时:

std::vector<int &> hello;

我得到像

这样的可怕错误
  

错误C2528:'指针':指向引用的指针是非法的

我想将一堆对结构的引用放入向量中,这样我就不必插入指针了。为什么矢量会对此发脾气?我唯一的选择是使用指针向量吗?

9 个答案:

答案 0 :(得分:291)

像矢量这样的容器的组件类型必须是assignable。引用不可分配(您只能在声明它们时初始化它们,并且以后不能让它们引用其他内容)。其他不可分配的类型也不允许作为容器的组件,例如<{1}}是不允许的。

答案 1 :(得分:101)

是的,您可以查找std::reference_wrapper,模仿参考但可分配,也可以“重新安排”

答案 2 :(得分:27)

就其本质而言,引用只能在创建时设置;即,以下两行具有非常不同的效果:

int & A = B;   // makes A an alias for B
A = C;         // assigns value of C to B.

此外,这是非法的:

int & D;       // must be set to a int variable.

但是,在创建矢量时,无法在创建时为其项目指定值。你基本上只是制作了最后一个例子。

答案 3 :(得分:23)

Ion Todirel已经使用std::reference_wrapper提到了答案自C ++ 11 以来,我们有一种机制可以从std::vector检索对象,并使用std::remove_reference删除引用。下面给出了使用g++clang与选项
一起编译的示例 -std=c++11并成功执行。

#include <iostream>
#include <vector>
#include<functional>

class MyClass {
public:
    void func() {
        std::cout << "I am func \n";
    }

    MyClass(int y) : x(y) {}

    int getval()
    {
        return x;
    }

private: 
        int x;
};

int main() {
    std::vector<std::reference_wrapper<MyClass>> vec;

    MyClass obj1(2);
    MyClass obj2(3);

    MyClass& obj_ref1 = std::ref(obj1);
    MyClass& obj_ref2 = obj2;

    vec.push_back(obj_ref1);
    vec.push_back(obj_ref2);

    for (auto obj3 : vec)
    {
        std::remove_reference<MyClass&>::type(obj3).func();      
        std::cout << std::remove_reference<MyClass&>::type(obj3).getval() << "\n";
    }             
}

答案 4 :(得分:14)

boost::ptr_vector<int>可以使用。

修改是使用std::vector< boost::ref<int> >的建议,由于您无法默认构建boost::ref,因此无效。

答案 5 :(得分:12)

这是C ++语言的一个缺陷。您不能获取引用的地址,因为尝试这样做会导致引用对象的地址,因此您永远无法获得指向引用的指针。 std::vector使用指向其元素的指针,因此需要能够指出存储的值。你必须使用指针。

答案 6 :(得分:3)

正如其他人所提到的,你最终可能会使用指针向量。

但是,您可能需要考虑使用ptr_vector代替!

答案 7 :(得分:0)

正如其他评论所暗示的那样,你只能使用指针。 但如果它有帮助,这里有一种技术可以避免直接面对指针。

您可以执行以下操作:

vector<int*> iarray;
int default_item = 0; // for handling out-of-range exception

int& get_item_as_ref(unsigned int idx) {
   // handling out-of-range exception
   if(idx >= iarray.size()) 
      return default_item;
   return reinterpret_cast<int&>(*iarray[idx]);
}

答案 8 :(得分:0)

TL; DR

像这样使用std::reference_wrapper

#include <functional>
#include <string>
#include <vector>
#include <iostream>

int main()
{
    std::string hello = "Hello, ";
    std::string world = "everyone!";
    typedef std::vector<std::reference_wrapper<std::string>> vec_t;
    vec_t vec = {hello, world};
    vec[1].get() = "world!";
    std::cout << hello << world << std::endl;
    return 0;
}

Demo

长答案

standard suggests一样,对于包含类型X的对象的标准容器TT必须是Erasable中的X

Erasable表示以下表达式格式正确:

allocator_traits<A>::destroy(m, p)

A是容器的分配器类型,m是分配器实例,p是类型*T的指针。有关Erasable的定义,请参见here

默认情况下,std::allocator<T>用作向量的分配器。使用默认分配器,要求等同于p->~T()的有效性(请注意,T是引用类型,而p是指向引用的指针)。但是,pointer to a reference is illegal导致该表达式的格式不正确。