Jak przekazać do tablicy obiektów parametr do konstruktora?

Odpowiedz Nowy wątek
2015-06-25 21:03
0

Witajcie,

Jak mogę stworzyć dynamiczną tablice obiektów klasy, żeby każdy konstruktor klasy dostał parametr o takiej samej wartości? Jest w ogóle taka możliwość czy dać sobie spokój i napisać osobną metodę którą muszę wykonać na każdym elemencie. Widziałem też sposób ze statyczną zmienną w klasie którą używał konstruktor (tylko czy to dobry "wzorzec"?). Zostaje tablica wskaźników na wskaźnik, ale mi chodzi o ciągły blok pamięci.


128 postów [25.06.2015r. 21:03]

Pozostało 580 znaków

2015-06-25 21:59

Teoretycznie jest taka możliwość, ale to mało znana składnia i każdy będzie się dziwił WTF.

#include <iostream>
using namespace std;

class Klasa
{
    int i;
public:
    Klasa(int ai)
        : i(ai)
    {
        cout << i << ' ';
    }
    ~Klasa()
    {
        cout << '~' << i << ' ';
    }
};

int main()
{
    Klasa *tablica;
    int len = 5;

    tablica = (Klasa*) malloc(sizeof(Klasa) * len);
    for (int i = 0; i < len; i++)
        new(&tablica[i]) Klasa(42);

    // teraz zwalniamy:

    for (int i = 0; i < len; i++)
        tablica[i].~Klasa();
    free(tablica);
}

Jak widzisz zwolnienie takiej tablicy też nie jest zbyt piękne.

edytowany 2x, ostatnio: Azarien, 2015-06-26 13:31
Pokaż pozostałe 18 komentarzy
@Endrju: sizeof poprawiony. i uważasz, że to static_cast&lt;Klasa*&gt;(operator new[] jest czytelniejsze od (Klasa*)malloc? - Azarien 2015-06-26 13:32
Tak wygląda C++ i tak się w nim pisze. - Endrju 2015-06-26 13:35
@Azarien: nie jest czytelniejsze, ale static_cast jest zalecanym sposobem konwersji dla C++ - w tym wypadku. - vpiotr 2015-06-26 13:39
e tam. to sobie poprawcie. ja nie będę zaciemniał kodu :-) - Azarien 2015-06-26 13:44
dupowatość C++ polega na tym że każde z tych rozwiązań może być OK w zależności od środowiska/kompilatora/standardów w firmie. - vpiotr 2015-06-26 13:49

Pozostało 580 znaków

2015-06-26 10:44
2

BTW - a czemu nie użyć std::vector? Ciągłość pamięci będzie zachowana, a używać tego wygodniej.

@MarekR22 brak konstruktora kopiującego faktycznie może być problematyczny. Ale Nie musisz przecież wywoływać domyślnego konstruktora:

#include <iostream>
#include <vector>

class Foo {
    private:
        int x;
    public:
        Foo(int a)
        : x(a) {}

        Foo() : Foo(5){}
        Foo(const Foo&) = default;
        Foo(Foo&&) = default;
    void print() const { std::cout << x << std::endl;}
};

int main(void) {
    // your code goes here
    std::vector<Foo> v;

    for (unsigned i = 0 ; i < 10 ; ++i) {
        v.emplace_back(Foo{(i*(9+i))});
    }

    for (const auto& el: v) {
        el.print();
    }
    return 0;
}
edytowany 1x, ostatnio: alagner, 2015-06-26 14:14
no bo chodzi o to by wywołać jakiś konkretny konstruktor, a nie domyślny (którego może nie być). Brak konstruktora kopiującego też stwarza problemy. - MarekR22 2015-06-26 13:49

Pozostało 580 znaków

2015-06-26 11:16
1

Pomyślałem sobie że musi się to dać zrobić bardziej na sposób C++:

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Klasa
{
    int value_;
public:
    Klasa(int ai)
        : value_(ai)
    {
        cout << value_ << ' ';
    }
    ~Klasa()
    {
        cout << '~' << value_ << ' ';
    }
    int getValue() { return value_; }
};

int main()
{
    cout << "--- start ---\n";

    Klasa prototype(42);
    int len =  10;
    shared_ptr<vector<Klasa> > myarray(new vector<Klasa>(len, prototype));
    cout << "\n--- array ready ---\n";

    for (int i = 0; i < myarray->size(); i++)
        cout << (*myarray)[i].getValue() << endl;

    cout << "--- stop ---\n";
}

http://ideone.com/uY80dF

Edit: wersja bardziej dynamiczna.

Edit: przerobione na vector, przykład nie miał nic wspólnego z przetwarzaniem wektorowym wartości skalarnych (valarray) i dodatkowo dzięki temu zniknęła jedna niepotrzebna alokacja/destrukcja.


Szacuje się, że w Polsce brakuje 50 tys. programistów
edytowany 6x, ostatnio: vpiotr, 2015-06-26 13:59
no ale to nie jest dynaczmina tablica tak jak chcial uzytkownik. - fasadin 2015-06-26 11:18
Wtf, sposób C++ nazywa się std::vector. - Endrju 2015-06-26 12:04
@Endrju: przerobione, rzeczywiście valarray był niepotrzebny. - vpiotr 2015-06-26 14:01

Pozostało 580 znaków

2015-06-26 13:40
1

"Sposób C++" na siłę jest np. taki:

#include <iostream>
#include <memory>
#include <cstddef>

class X {
public:
  X(int x) : mX(x) { std::cout << "X(" << mX << ")\n"; }
  X(const X &other) : mX(other.mX) { std::cout << "copy X, mX = " << mX << '\n'; }
  ~X() { std::cout << "~X(" << mX << ")\n"; }

  int mX;
};

int main() {
  const std::size_t arraySize = 5u;
  std::allocator<X> allocator;

  X *array = allocator.allocate(arraySize);

  const X prototypeX(42);
  std::uninitialized_fill_n(array, arraySize, prototypeX);

  for (std::size_t i = 0; i < arraySize; ++i) {
    allocator.destroy(array + i);
  }

  allocator.deallocate(array, arraySize);
}

http://ideone.com/FbD63r

Ale jedyny sensowny sposób to std::vector.


"(...) otherwise, the behavior is undefined".
edytowany 3x, ostatnio: Endrju, 2015-06-26 13:52

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0