为什么我不能创建引用向量?

发布于 2024-07-23 11:33:34 字数 324 浏览 3 评论 0原文

当我这样做时:

std::vector<int> hello;

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

std::vector<int &> hello;

我收到可怕的错误,例如

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

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

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

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?

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

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

发布评论

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

评论(11

画中仙 2024-07-30 11:33:34

向量等容器的组件类型必须是可分配 。 引用是不可分配的(您只能在声明它们时初始化它们一次,并且以后不能让它们引用其他内容)。 其他不可分配的类型也不允许作为容器的组件,例如不允许vector

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.

初见终念 2024-07-30 11:33:34

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

风透绣罗衣 2024-07-30 11:33:34

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

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.

但是,当您创建向量时,无法在创建时为其项目赋值。 您实际上只是在制作最后一个示例的一大堆内容。

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.

花落人断肠 2024-07-30 11:33:34

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

演示

长答案

作为标准建议,用于包含对象的标准容器 X类型为 TT 必须可从 XErasable

Erasable 表示以下表达式格式良好:

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

A 是容器的分配器类型,m 是分配器实例,p是一个*T类型的指针。 请参阅此处了解Erasable定义。

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

TL; DR

Use std::reference_wrapper like this:

#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

Long answer

As standard suggests, for a standard container X containing objects of type T, T must be Erasable from X.

Erasable means that the following expression is well formed:

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

A is container's allocator type, m is allocator instance and p is a pointer of type *T. See here for Erasable definition.

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 T is a reference type and p is pointer to a reference). However, pointer to a reference is illegal, hence the expression is not well formed.

你不是我要的菜∠ 2024-07-30 11:33:34

Ion Todirel 已经使用 std::reference_wrapper 提到了答案YES自 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";
        }             
    }

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

    #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";
        }             
    }
旧话新听 2024-07-30 11:33:34

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

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::vector works 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.

淡淡绿茶香 2024-07-30 11:33:34

boost::ptr_vector会起作用。

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

boost::ptr_vector<int> will work.

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

随梦而飞# 2024-07-30 11:33:34

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

但是,您可能需要考虑使用 ptr_vector 相反!

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

However, you may want to consider using a ptr_vector instead!

赠佳期 2024-07-30 11:33:34

中找到了原因

我在C++14《国际标准ISO/IEC 14882:2014(E)编程语言C++》 [8.3.2-5.s1]
不应存在​​对引用的引用、引用数组和指向引用的指针。

I found the reason in C++14, "International Standard ISO/IEC 14882:2014(E) Programming Language C++"

[8.3.2-5.s1]
There shall be no references to references, no arrays of references, and no pointers to references.

哑剧 2024-07-30 11:33:34

没有技术原因导致您不能拥有引用向量,它只是不是 API 的一部分,大概是为了使其与数组类似。 可以轻松添加与引用一起使用的专业化,将它们存储为内部指针并在 API 中呈现为引用:

vector<int&> ivref;
int i = 42;
ivref.push_back(i); // address of i is stored
ivref.front() = 43; // i is set to 43
ivref.push_back(44); // Marked deleted for rvalue references 
ivref.resize(10);    // Marked deleted for vector of references

There is no technical reason why you couldn't have a vector of references, it's just not a part of the API, presumably to keep it similar to an array. A specialization could easily be added that works with references, stores them as pointers internally and presents as references in the API:

vector<int&> ivref;
int i = 42;
ivref.push_back(i); // address of i is stored
ivref.front() = 43; // i is set to 43
ivref.push_back(44); // Marked deleted for rvalue references 
ivref.resize(10);    // Marked deleted for vector of references
飘过的浮云 2024-07-30 11:33:34

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

您可以执行以下操作:

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

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