Programing

왜 참조 벡터를 만들 수 없습니까?

lottogame 2020. 3. 6. 08:15
반응형

왜 참조 벡터를 만들 수 없습니까?


내가 이것을 할 때 :

std::vector<int> hello;

모든 것이 잘 작동합니다. 그러나 대신 참조 벡터로 만들면 :

std::vector<int &> hello;

나는 끔찍한 오류를 얻는다

오류 C2528 : '포인터': 참조 포인터가 잘못되었습니다

구조체에 대한 많은 참조를 벡터에 넣고 싶습니다. 그래서 포인터로 방해 할 필요가 없습니다. 왜 이것에 대해 벡터가 울화를 일으키는가? 대신 포인터 벡터를 사용하는 유일한 옵션입니까?


벡터와 같은 컨테이너의 구성 요소 유형은 지정 가능 해야합니다 . 참조는 할당 할 수 없습니다 (선언 될 때 한 번만 초기화 할 수 있으며 나중에 참조 할 수는 없습니다). 다른 비 할당 유형은 컨테이너 구성 요소로 vector<const int>허용되지 않습니다 ( 예 : 허용되지 않음).


std::reference_wrapper, 참조를 모방하지만 할당 가능하고 "재 장착"될 수있는를 찾을 수 있습니다.


본질적으로 참조는 생성 된 시점에만 설정할 수 있습니다. 즉, 다음 두 줄은 매우 다른 효과를 갖습니다.

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.

그러나 벡터를 생성 할 때는 생성시 해당 항목에 값을 할당 할 방법이 없습니다. 당신은 본질적으로 마지막 예제를 전부 다 만들고 있습니다.


Ion Todirel은 이미을 사용하여 YES라고 대답했습니다 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";
    }             
}

boost::ptr_vector<int> 작동합니다.

편집 : 을 사용하는 것이 좋습니다 std::vector< boost::ref<int> >. 이는 기본 구성을 할 수 없기 때문에 작동하지 않습니다 boost::ref.


C ++ 언어의 결함입니다. 참조 주소를 가져 오면 참조 된 오브젝트의 주소가 생성되므로 참조에 대한 포인터를 얻을 수 없으므로 참조 주소를 사용할 수 없습니다. std::vector요소에 대한 포인터와 함께 작동하므로 저장되는 값을 가리킬 수 있어야합니다. 대신 포인터를 사용해야합니다.


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

긴 대답

으로 표준 제안 , 표준 컨테이너 X유형의 객체를 포함 T, T수 있어야 Erasable에서 X.

Erasable 다음식이 잘 구성되어 있음을 의미합니다.

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

A컨테이너의 할당 자 유형이고 m할당 자 인스턴스이며 p유형의 포인터입니다 *T. 정의는 여기참조 하십시오Erasable .

기본적 std::allocator<T>으로 벡터의 할당 자로 사용됩니다. 기본 할당 자에서 요구 사항은 유효성과 같습니다 p->~T()(참고 T는 참조 유형이며 참조에 대한 p포인터 임). 그러나 참조에 대한 포인터는 불법 이므로 표현식이 제대로 구성되지 않았습니다.


다른 사람들이 언급했듯이, 대신 포인터 벡터를 사용하게 될 것입니다.

그러나 대신 ptr_vector사용하는 것이 좋습니다!


다른 의견에서 알 수 있듯이 포인터 사용에 국한됩니다. 그러나 그것이 도움이된다면, 포인터와 직접 대면하지 않는 한 가지 기술이 있습니다.

다음과 같은 작업을 수행 할 수 있습니다.

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

참고 URL : https://stackoverflow.com/questions/922360/why-cant-i-make-a-vector-of-references



반응형