Usuwanie obiektu z wektora

0

Witam,
Mam taki kod, jak najprostszym sposobem klasa może usunąć samą siebie z wektora ją zawierającego? Jedyne co mi przychodzi do głowy to przekazanie w parametrze pointera na vector i pozycję klasy w nim ale wydaje mi się że to niezbyt dobre rozwiązanie.

#include <vector>
#include <thread>

class Class
{
public:
	Class()
	{
		std::thread Thread(&Class::DoSomething, this);
		Thread.join();
	}
	
	void DoSomething()
	{
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
};

int main()
{
	std::vector<Class>Vector;

	while (true)
	{
		Vector.push_back(Class());
		printf("Vector size - %i\n", Vector.size());
	}
}
4
  1. Usuwanie samego siebie z listy u kogoś innego to potencjalny błąd designowy.
  2. Jeśli używasz wielowątkowości pamiętaj o synchronizacji, inaczej będziesz miał UB.
  3. Śmierdzi mi to problemem XY: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem
0

Chodzi mi o coś takiego, to działa ale wydaje mi się że nie powinno się tak robić i że są lepsze sposoby.

#include <vector>
#include <thread>

class Class
{
public:
	Class(std::vector<Class>*PointerToVector, int Position)
	{
		std::thread Thread(&Class::DoSomething, this);
		Thread.join();
		PointerToVector->erase(PointerToVector->begin() + Position);
	}

	void DoSomething()
	{
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
};

int main()
{
	std::vector<Class>Vector;

	while (true)
	{
		Vector.push_back(Class(&Vector, Vector.size()));
		printf("Vector size - %i\n", Vector.size());
	}
}
3

Ten kod to jedno wielkie UB. W konstruktorze obiektu jesteś zanim dodasz go do wektora (poprzez copy/move w push_back), więc próbujesz erase'ować Vector.end(). Powiedz co chcesz osiągnąć zamiast pytać jak naprawić błędne rozwiązanie, które sobie upatrzyłeś.

0

Może ten przykład bardziej zobrazuje o co mi chodzi.
Generalnie chciałbym mieć vector wątków do którego wsadzam obiekt, konstruktor powinien wywołać się w nowym wątku, gdy obiekt skończy swoją pracę po prostu kasuje swój wątek z vectora. To co zrobiłem crashuje przy usuwaniu, w sumie nie wiem dlaczego.

#include <vector>
#include <thread>

class Class
{
public:
	Class()
	{
		printf("Class::Class()\n");
		std::this_thread::sleep_for(std::chrono::seconds(10));
	}
};

void AddNewClass(std::vector<std::thread>*Vector, int Position)
{
	printf("AddNewClass()\n");
	Class();
	Vector->erase(Vector->begin() + Position);
}

int main()
{
	std::vector<std::thread>Vector;

	while (true)
	{
		Vector.push_back(std::thread(AddNewClass, &Vector, Vector.size()));
		printf("Vector size - %i\n", Vector.size());
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
}
1

Próbujesz usuwać elementy z pustego wektora. Ciekawe dlaczego to nie działa.

0

@kq Nie bardzo rozumiem co masz na myśli, przecież on nie jest pusty :/

2

Ech, faktycznie, źle spojrzałem. Tak czy inaczej masz niesynchronizowane modyfikacje tego samego obiektu z różnych wątków. Patrz punkt 2) mojego posta wyżej. Ponadto pozycja w wektorze podczas tworzenia i usuwania nie jest ta sama, więc erase (pomijając wyścig) dostaje inny obiekt lub iterator na coś zupełnie poza wektorem.

1

Ten kod jest zły z wielu powodów. O niektórych już wspomniał @kq, ale jest jeszcze problem z brakiem join() lub detach(). Jeżeli wątek nie został joinowany lub detachowany przed wywołaniem destruktora obiektu std::thread to się wywoła terminate() i program zostanie ubity.

Poza tym nadal nie rozumiem, po co chcesz usunąć te obiekty z wektora. Zostaw je sobie tam, jak wektora zostanie zniszczony to sam się posprząta (oczywiście wcześniej trzeba zadbać o odpowiednie zakończenie wątków - nie mylić ze zniszczeniem obiektów std::thread).

No i oczywiście w tej postaci sam sens istnienia wektora mi umyka. Chcesz dodać wątek do wektora tylko po to żeby zaraz go usunąć?

Jako bonusik: jeżeli wektor ma size() elementów, to ostatni element ma indeks size()-1.

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