C++ 为什么我不能制作参考向量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/922360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:58:09  来源:igfitidea点击:

Why can't I make a vector of references?

c++vectorreferencestlcontainer-data-type

提问by Colen

When I do this:

当我这样做时:

std::vector<int> hello;

Everything works great. However, when I make it a vector of references instead:

一切都很好。但是,当我将其设为引用向量时:

std::vector<int &> hello;

I get horrible errors like

我得到了可怕的错误,比如

error C2528: 'pointer' : pointer to reference is illegal

错误 C2528:“指针”:指向引用的指针非法

I want to put a bunch of references to structs into a vector, so that I don't have to meddle with pointers. Why is vector throwing a tantrum about this? Is my only option to use a vector of pointers instead?

我想将一堆对结构的引用放入一个向量中,这样我就不必干预指针了。为什么vector会对此大发雷霆?我唯一的选择是使用指针向量吗?

回答by newacct

The component type of containers like vectors must be assignable. References are not assignable (you can only initialize them once when they are declared, and you cannot make them reference something else later). Other non-assignable types are also not allowed as components of containers, e.g. vector<const int>is not allowed.

容器等容器的组件类型必须是可分配的。引用是不可赋值的(你只能在声明时初始化它们一次,以后不能让它们引用其他东西)。其他不可分配的类型也不允许作为容器的组件,例如vector<const int>不允许。

回答by Ion Todirel

yes you can, look for std::reference_wrapper, that mimics a reference but is assignable and also can be "reseated"

是的,你可以,寻找std::reference_wrapper,模仿参考但可分配,也可以“重新安装”

回答by James Curran

By their very nature, references can only be set at the time they are created; i.e., the following two lines have very different effects:

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

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

Futher, this is illegal:

此外,这是非法的:

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

However, when you create a vector, there is no way to assign values to it's items at creation. You are essentially just making a whole bunch of the last example.

但是,当您创建向量时,无法在创建时为其项目分配值。你基本上只是在制作最后一个例子的一大堆。

回答by Steephen

Ion Todirel already mentioned an answer YESusing std::reference_wrapper. Since C++11we have a mechanism to retrieve object from std::vectorand remove the reference by using std::remove_reference. Below is given an example compiled using g++and clangwith option
-std=c++11and executed successfully.

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

回答by Drew Dormann

boost::ptr_vector<int>will work.

boost::ptr_vector<int>将工作。

Edit:was a suggestion to use std::vector< boost::ref<int> >, which will not work because you can't default-construct a boost::ref.

编辑:建议使用std::vector< boost::ref<int> >,这将不起作用,因为您无法默认构建boost::ref.

回答by Adam Rosenfield

It's a flaw in the C++ language. You can't take the address of a reference, since attempting to do so would result in the address of the object being referred to, and thus you can never get a pointer to a reference. std::vectorworks with pointers to its elements, so the values being stored need to be able to be pointed to. You'll have to use pointers instead.

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

回答by ivaigult

TL; DR

TL; DR

Use std::reference_wrapperlike this:

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

Demo

Long answer

长答案

As standard suggests, for a standard container Xcontaining objects of type T, Tmust be Erasablefrom X.

正如标准建议的那样,对于X包含类型对象的标准容器TT必须Erasable来自X.

Erasablemeans that the following expression is well formed:

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

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

Ais container's allocator type, mis allocator instance and pis a pointer of type *T. See herefor Erasabledefinition.

A是容器的分配器类型,m是分配器实例,p是类型为 的指针*T。见这里Erasable定义。

By default, std::allocator<T>is used as vector's allocator. With the default allocator, the requirement is equivalent to the validity of p->~T()(Note the Tis a reference type and pis pointer to a reference). However, pointer to a reference is illegal, hence the expression is not well formed.

默认情况下,std::allocator<T>用作向量的分配器。使用默认分配器,要求等效于p->~T()(注意T是引用类型并且p是指向引用的指针)的有效性。但是,指向引用的指针是非法的,因此表达式的格式不正确。

回答by Martin Cote

As other have mentioned, you will probably end up using a vector of pointers instead.

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

However, you may want to consider using a ptr_vectorinstead!

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

回答by Omid

As the other comments suggest, you are confined to using pointers. But if it helps, here is one technique to avoid facing directly with pointers.

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

You can do something like the following:

您可以执行以下操作:

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]);
}