2012-10-16 15 views
5

Chcę zapisać listę obiektów w obiekcie std::vector, ale obiekty zawierają odwołanie i nie można do nich przypisać. Mogę jednak skopiować - skonstruować obiekt.C++ Użyj nieprzypisanych obiektów w wektorze

Jedyną opcją, o której mogę pomyśleć, to użycie wskaźników do zawijania obiektów i ponownego umieszczenia wskaźników, gdy trzeba je przypisać, ale składnia tego spowodowałaby znaczne zmniejszenie czytelności, szczególnie w przypadku korzystania z iteratorów, a ja wolałbym alternatywny.

nie działa:

std::vector<MyObject> myVector; 
//fill the vector 
//... 
myVector[1] = object1; 

inteligentne kursory ofiara czytelność:

std::vector<std::unique_ptr<MyObject>> ptrVector; 
//fill the vector 
//... 
ptrVector[1] = std::unique_ptr<MyObject>(new MyObject(object1)); 

Czy są jakieś inne sposoby korzystania nieprzenoszalnym obiektów w std::vector?

+0

Zakładając C++ 11, by za pomocą 'std :: reference_wrapper' zamiast tradycyjnych odniesień być rozwiązanie? – jogojapan

+0

Nie sądzę, że potrzebujesz 'std :: move' w ostatnim wierszu kodu, ponieważ' std :: unique_ptr (...) 'jest wartością r. –

+0

@ DavidRodríguez-dribeas O tak, naprawiłem to w pytaniu. –

Odpowiedz

2

To nie jest bezpośrednia odpowiedź na twoje pytanie, ponieważ nie mogę zaoferować zamiennika dla std::vector, ani innego sposobu używania go, który pozwala ci robić to, czego potrzebujesz.

Jeśli jednak możliwa jest modyfikacja definicji MyObject, może być dostępna opcja zmiany tej wartości, aby zamiast standardowych odwołań używać std::reference_wrapper. To pozwoliłoby na przypisanie MyObject.

przykład:

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

struct MyObject 
{ 
    //int &_i; 
    std::reference_wrapper<int> _i; 
    MyObject(int &i):_i(i) {} 
}; 


int main() { 
    std::vector<MyObject> vec; 
    int i1 = 3; 
    int i2 = 4; 
    MyObject c1(i1); 
    MyObject c2(i2); 

    /* Storing object. */ 
    vec.push_back(c1); 

    /* Assigning to it. */ 
    vec[0] = c2; 

    /* Confirming that it's the correct object now. */ 
    for (const MyObject &it : vec) 
    std::cout << it._i << std::endl; 

    /* Modifying the value of its internal reference. */ 
    vec[0]._i.get() = 5; 
    /* Confirming that the original int changed value indeed. */ 
    std::cout << "i2 == " << i2 << std::endl; 

    return 0; 
} 

Zastrzeżenie: istniejący kod może już zawierać bezpośrednie przypisania do elementu odniesienia (to jest element nazywany _i w kodzie powyżej). Te przypisania miały na celu zmianę wartości obiektu, do którego odnosi się odniesienie. Wymieniając odniesienie na std::reference_wrapper, wszystkie bezpośrednie przypisania _i = x muszą zostać zastąpione przez _i.get() = x, w przeciwnym razie semantyka programu zmieni się całkowicie.

(EDYCJA) Jeśli użyte referencje są odniesieniami const T&, można użyć std::reference_wrapper<const T>. Korzystając z przykładu powyżej, definicja MyObject następnie zmienia się w ten sposób:

struct MyObject 
{ 
    std::reference_wrapper<const int> _i; 
    MyObject(const int &i):_i(i) {} 
}; 
+0

Właśnie zdałem sobie sprawę, że obiekt zawiera odwołanie do 'const', więc zmiana odniesień do wrapperów tutaj nie pomoże. Zmieniłem moje pytanie, aby odzwierciedlić zmianę. –

+0

Możesz użyć 'std :: reference_wrapper ' (i zastąp 'int' typem, którego używasz) w tym przypadku. – jogojapan

+0

Oh, haha, kiedy testowałem to użyłem 'const std :: reference_wrapper '. Wróciłem do pytania. Dzięki za pomoc! –

0

Dlaczego nie dokonać przypisania "MyObject"? Możesz zastąpić operatora "=", w ten sposób "myVector [1] = object1" będzie działać.

+1

Ponieważ 'MyObject' zawiera odniesienie jako element członkowski. – jogojapan

Powiązane problemy