Przesyłanie oryginalnych zmiennych do klasy

Przesyłanie oryginalnych zmiennych do klasy
Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Witam,
Mam mały problem z moim programem. Mianowicie w klasie Joiner w konstruktorze przesyłam dwa kontenery, ale niestety przesyłam ich kopię, a nie oryginały.
Czy mógłby mi ktoś pomóc jak przesłać oryginalne zmienne, tak żeby funkcje:

*JoinAtBegin() (dodaje na początek kontener który jest podany jako drugi w konstruktorze do tego pierwszego)

*JoinAtEnd() (dodaje na koniec kontener który jest podany jako drugi w konstruktorze do tego pierwszego)
zmieniały kontenery z funkcji main() , a nie te wewnątrz klasy? Poniżej zamieszczam kod:

Kopiuj

#include <iostream>
#include<vector>
#include <list>
#include <deque>
#include <random>
#include <chrono>
#include <iterator>
#include <utility>
using Vector = std::vector<double>;
using List = std::list<double>;


template <typename T, typename L>
class Joiner
{
public:
    Joiner(T& container1, L& container2)
    {
        container1_ = container1;
        container2_ = container2;
    }
    void joinAtBegin()
    {
        auto it = container1_.begin();
        auto it2 = container2_.begin();
        container1_.insert(it, it2, it2 = container2_.end());
    }
    void joinAtEnd()
    {
        auto it = container1_.end();
        auto it2 = container2_.begin();
        container1_.insert(it, it2, it2 = container2_.end());
    }
    void showResults()
    {
        std::cout << "kontener 1 z klasy Joiner: " << container1_.size() << std::endl;
        std::cout << "kontener 2 z klasy Joiner: " << container2_.size() << std::endl;       
    }
private:
    T container1_;
    L container2_;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main() {
    Vector v1(1000,1.0),v2(1000,2.0);
    List l1(1000,3.0),l2(1000,4.0);
    Joiner <Vector, Vector > joiner1{v1, v2};
    Joiner <List, List > joiner2{l1, l2};
    Joiner <Vector, List > mixedJoiner{v1, l1};

    std::cout << "joiner1: " << std::endl;
    std::cout << "v1 z funkcji main przed: " << v1.size() << std::endl;
    std::cout << "v2 z funkcji main przed: " << v2.size() << std::endl;
    joiner1.joinAtBegin();
    joiner1.joinAtEnd();
    joiner1.showResults();
    std::cout << "v1 z funkcji main po: " << v1.size() << std::endl;
    std::cout << "v2 z funkcji main po: " << v2.size() << std::endl << std::endl;
    
    std::cout << "joiner2: " << std::endl;
    std::cout << "l1 z funkcji main przed: " << l1.size() << std::endl;
    std::cout << "l2 z funkcji main przed: " << l2.size() << std::endl;
    joiner2.joinAtBegin();
    joiner2.joinAtEnd();
    joiner2.showResults();
    std::cout << "l1 z funkcji main po: " << v1.size() << std::endl;
    std::cout << "l2 z funkcji main po: " << v2.size() << std::endl << std::endl;
    
    std::cout << "mixedjoiner: " << std::endl;
    std::cout << "l1 z funkcji main przed: " << l1.size() << std::endl;
    std::cout << "l2 z funkcji main przed: " << l2.size() << std::endl;
    mixedJoiner.joinAtBegin();
    mixedJoiner.joinAtEnd();
    mixedJoiner.showResults();
    std::cout << "l1 z funkcji main przed: " << l1.size() << std::endl;
    std::cout << "l2 z funkcji main przed: " << l2.size() << std::endl;
    return 0;
}

po wywołaniu programu otrzymuję taki wynik (zdjęcie w załączniku)

Czyli w funkcjach JoinAtBegin() i JoinAtEnd() wielkość wektorów się zwiększa, ale kontenery z funkcji main pozostają bez zmiany(nadal mają 1000 elementów), a chcę żeby właśnie te kontenery z maina się zmieniały.
Z góry dziękuję za odpowiedź. Pozdrawiam

AK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3561
1

Pewnie ci chodzi o:

Kopiuj
private:
    T & container1_;
    L & container2_;

I być moze konstruktor będzie musiał być formalnie przepisany

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

wtedy wyskakuję masa błędów:

Kopiuj
main.cpp:61:5: error: constructor for 'Joiner<std::vector<double, std::allocator<double> >, std::vector<double, std::allocator<double> > >' must explicitly initialize the reference member 'container1_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:118:30: note: in instantiation of member function 'Joiner<std::vector<double, std::allocator<double> >, std::vector<double, std::allocator<double> > >::Joiner' requested here
    Joiner <Vector, Vector > joiner1{v1, v2};
                             ^
main.cpp:108:8: note: declared here
    T& container1_;
       ^
main.cpp:61:5: error: constructor for 'Joiner<std::vector<double, std::allocator<double> >, std::vector<double, std::allocator<double> > >' must explicitly initialize the reference member 'container2_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:109:8: note: declared here
    L& container2_;
       ^
main.cpp:61:5: error: constructor for 'Joiner<std::__cxx11::list<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >' must explicitly initialize the reference member 'container1_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:119:26: note: in instantiation of member function 'Joiner<std::__cxx11::list<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >::Joiner' requested here
    Joiner <List, List > joiner2{l1, l2};
                         ^
main.cpp:108:8: note: declared here
    T& container1_;
       ^
main.cpp:61:5: error: constructor for 'Joiner<std::__cxx11::list<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >' must explicitly initialize the reference member 'container2_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:109:8: note: declared here
    L& container2_;
       ^
main.cpp:61:5: error: constructor for 'Joiner<std::vector<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >' must explicitly initialize the reference member 'container1_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:120:28: note: in instantiation of member function 'Joiner<std::vector<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >::Joiner' requested here
    Joiner <Vector, List > mixedJoiner{v1, l1};
                           ^
main.cpp:108:8: note: declared here
    T& container1_;
       ^
main.cpp:61:5: error: constructor for 'Joiner<std::vector<double, std::allocator<double> >, std::__cxx11::list<double, std::allocator<double> > >' must explicitly initialize the reference member 'container2_'
    Joiner(T& container1, L& container2)
    ^
main.cpp:109:8: note: declared here
    L& container2_;
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
2

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

AK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3561
1

*must explicitly initialize the reference member 'container1_' *
się tłumaczy, jak już wspominałem:

Kopiuj
  Joiner(T& container1, L& container2) :   container1_(container1),    container2_ (container2)
    {
    }

To nie twój kod?

MarekR22 napisał(a):

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

Za bardzo jestem zmęczony by podjąć ten wątek

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0
MarekR22 napisał(a):

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

Dlaczego?
dodaje kontenery, bo sprawdzałem?

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0
AnyKtokolwiek napisał(a):
  • must explicitly initialize the reference member 'container1_' *
    się tłumaczy, jak już wspominałem:
Kopiuj
  Joiner(T& container1, L& container2) :   container1_(container1),    container2_ (container2)
    {
    }

To nie twój kod?

Mój, sam pisałem...

MarekR22 napisał(a):

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

Za bardzo jestem zmęczony by podjąć ten wątek

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0
AnyKtokolwiek napisał(a):

*must explicitly initialize the reference member 'container1_' *
się tłumaczy, jak już wspominałem:

Kopiuj
  Joiner(T& container1, L& container2) :   container1_(container1),    container2_ (container2)
    {
    }

To nie twój kod?

MarekR22 napisał(a):

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

Za bardzo jestem zmęczony by podjąć ten wątek

Dobra dziękuję, zmiana konstruktora na ten od "AnyKtokolwiek" rozwiązała problem.
dziękuję wszystkim :)

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Działa, jak należy

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

a, tak z ciekawości, dlaczego nie można zdefiniować konstruktora tak, jak wcześniej zdefiniowałem?

AK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3561
2
Zdzisław Puchaty napisał(a):

a, tak z ciekawości, dlaczego nie można zdefiniować konstruktora tak, jak wcześniej zdefiniowałem?

Zmienne referencyjna w C++ nie może być ani mikrosekundy nie-zainicjowana, czyli bardziej ściślej musi byś zainicjowana z chwilą tworzenia.
Twój sposób - obrazowo mówiąc - robi to minimalnie później.

Oczywiście istnieje wyjaśnienie bardziej formalne, oparte na standardach itd.

Zdzisław Puchaty
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0
AnyKtokolwiek napisał(a):
Zdzisław Puchaty napisał(a):

a, tak z ciekawości, dlaczego nie można zdefiniować konstruktora tak, jak wcześniej zdefiniowałem?

Zmienne referencyjna w C++ nie może być ani mikrosekundy nie-zainicjowana, czyli bardziej ściślej musi byś zainicjowana z chwilą tworzenia.
Twój sposób - obrazowo mówiąc - robi to minimalnie później.

Oczywiście istnieje wyjaśnienie bardziej formalne, oparte na standardach itd.

Ok, rozumiem
Jeszcze raz, Wielkie dzięki

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1
Zdzisław Puchaty napisał(a):
MarekR22 napisał(a):

Dla mnie tak klasa nic nie robi. Ja bym ja bym ją skasował bez mrugnięcia okiem.

Dlaczego?
dodaje kontenery, bo sprawdzałem?

Tak dodaje kontenery, ale robi to w taki sposób, żeby utrudnić czytanie kodu i jego rozumienie.
Ta klasa magicznie zmienia wartości, które kiedyś w przeszłości zostały jej przekazane.
Ktoś kto potem będzie czytał ten, kod będzie szukał czemu mu się te zmienne zmieniają i będzie miał kłopot ze zrozumieniem, że to się dzieje w zupełnie innym miejscu.
To jest najgorszy przypadek nieoczekiwanego side effect.

Na dodatek, o wile prościej i czytelniej mieć po prostu funkcje:

Kopiuj
template <typename T, typename L>
void prepend(T& dst, const L& src)
{
     dst.insert(insert.begin(), src.begin(), src.end());
}

template <typename T, typename L>
void append(T& dst, const L& src)
{
     dst.insert(insert.end(), src.begin(), src.end());
}

Podczas użycia widać co się dzieje i będzie to w miarę oczywiste.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.