unique_ptr destruktor

0

Hej, już od dobrych kilku dni męczę się z unique_ptr, sprawa wygląda następująco:
chce na obiekcie określonej klasy wywołać metodę virtualną buildAST a następnie w tej metodzie przypisać startSymbolowi ten wskaźnik na którym została wywolana metoda buildAST :

void AbstractExpression::creatAST()
{
	tmp = parser->parse(); //parse() zwraca unique_ptr na obiekt określonej klasy
	while (tmp)
	{
		
		tmp->buildAST();
		tmp = std::move(parser->parse());
	}

}
template<typename T>
void Number<T>::buildAST()
{
	if (not startSymbol)
	{
		std::unique_ptr<Number<T>> tmp2 = std::make_unique<Number<T>>(this->getValue());
		this->startSymbol= std::move(tmp2)); //działa, przypisuje się ale po wyjściu z powrotem startSymbol jest pusty czyli wychodzi jakby został wywołany destruktor a tego nie chce jak to zmienić ? 
			
	}
	
}

class AbstractExpression
{	
	
protected:
	Parser *parser;
	
	std::unique_ptr<AbstractExpression> startSymbol;
	std::unique_ptr<AbstractExpression> leftNode;
	std::unique_ptr<AbstractExpression> rightNode;
	std::unique_ptr<AbstractExpression> tmp;
	//inne metody w tym buildAST();
}

Metoda buildAST() przypisuje startSymbolowi odp unique_ptr ale tylko wewnątrz jej ciała, po powrocie z powrotem do buildAST() i linijki chociażby tmp=std::move(parser.parse()); startSymbol jest pusty; jak sprawić aby nie był wywołany destruktor uniqe_ptr wewnątrz metody wirtualnej buildAST()? Czy może problem tkwi gdzie indziej? Jak sprawić aby startSymbol ustawiał się w klasie AbstractExpression a nie 'znikał';
Z góry dziękuję za odpowiedź lub jakąkolwiek wskazówkę!
Pozdrawiam A

0

Coś tu jest strasznie pomieszane. W kodzie, który pokazujesz, ustawiasz startSymbol dla obiektu klasy Number<T>, natomiast nigdzie nie widzę, żebyś ustawił dla klasy AbstractExpression.
Ale załóżmy, że robisz to gdzie indziej. Jak nie chcesz, żeby te obiekty unique_ptr zostały zniszczone, to musisz je gdzieś przechowywać, np. AbstractExpression może mieć

std::vector<std::unique_ptr<...>> cholerawiecotojest;

i potem możesz

tmp->buildAST();
cholerawiecotojest.push_back(std::move(tmp));
tmp = parser->parse();
0

Jak sprawić aby startSymbol ustawiał się w klasie AbstractExpression a nie 'znikał';

Usuń linię z std::move. Po co ona tam jest?

1

To jest typowy problem XY.
Robisz jakieś X, którego nie opisałeś i postanowiłeś zrobić to stosując metodę Y, która jest niepoprawna logicznie, więc ci nie działa.
Teraz przychodzisz do nas i prosisz by naprawić Y mimo, że jest niespójnie logicznie.

Jeśli opiszesz X to się okaże, że możesz zapomnieć o Y

A kodu widzę, że obiekt stworzony tu tmp = parser->parse(); przestaje istnieć zaraz po wywołaniu tmp->buildAST();, bo w następnej linijce tmp dostaje nową wartość.
Zresztą w tej linijce: tmp = std::move(parser->parse()); std::move jest zbędne.

0

Jest w tym projekcie sporo klas i nie chciałam nawrzucać tego aby było bardziej czytelne niestety widzę, że przyniosło to efekt odwrotny, wiec z góry przepraszam za to. A więc tak z AbstractExpression dziedziczy klasa TerminalExpression a z niej klasa Number tak jak pisal @_0x666_:

#pragma once
#include<iostream>
#include<typeinfo>
#include"TerminalExpression.h"
template<typename T>
class Number :public TerminalExpression 
{
	T value;
protected:
	//virtual Number<T>* clone_impl() const override { return new Number<T>(); };
public:
	Number();
	/*virtual std::unique_ptr<TerminalExpression> clone() const override
	{
		return std::make_unique<Number<T>>(*this);
	}*/
	Number(const T & val);
	bool operator==(const Number<T>& figure);
	virtual void buildAST();
	T getValue();
	Number<T>& operator=(Number<T>&& figure);
	~Number();

};
template<typename T>
Number <T>::Number()
{

}
template<typename T>
bool Number<T>::operator==(const Number<T>& figure)
{
	return value == figure.value;
}
template<typename T>
void Number<T>::buildAST()
{
	if (not startSymbol)
	{
		std::unique_ptr<Number<T>> tmp2 = std::make_unique<Number<T>>(this->getValue());
		this->startSymbol = std::move(tmp2); 

	}
	
}
template<typename T>
Number<T>::Number(const T & val)
	:value(val)
{

}
template<typename T>
Number<T>::~Number()
{

}

template<typename T>
T Number<T>::getValue()
{
	return value;
}

template<typename T>
inline Number<T>& Number<T>::operator=(Number<T>&& figure)
{
	if(*this!=figure)
	value = figure.value;

	return *this;
}

Zamiast vectora chce umieścić te obiekty w drzewie, dlatego chciałabym wywoływać na każdym z nich metodę buildAST(AbstractSyntaxTree) i dodawać do drzewa, którego: korzen, prawy i lewy wezel sa polami w klasie AbstractExpression. Nawet gdy zakomentuję linię : tmp=parser->parse(); niestety ciągle nie działa a nie przypisuje się już w miejscu kiedy wyjdę od razu z funkcji a jeszcze nie pobiorę nowego obiektu. @twonek napisałeś:

W kodzie, który pokazujesz, ustawiasz startSymbol dla obiektu klasy Number<T>, natomiast nigdzie nie widzę, żebyś ustawił dla klasy AbstractExpression

Chciałabym ustawić startSymbol dla klasy AbstractExpression ale przez wywołanie metody wirtualnej na obiekcie klasy Number, czy jest to możliwę czy muszę startSymbol ustawić w metodzie buildAST dla AbstractExpression czyli tam gdzie pobieram tmp w whilu i później przypisuje mu nową wartość? Metoda parse() zwraca mi wskaźnik na obiekt odpowiedniej klasy albo Numer albo NonTerminalExpression tzn Addition, Division etc. Z góry bardzo dziekuję za odpowiedź

0
Leks napisał(a):

Jest w tym projekcie sporo klas i nie chciałam nawrzucać tego aby było bardziej czytelne niestety widzę, że przyniosło to efekt odwrotny

Nie chodzi o to, żebyś wrzucał wszystko, ale zaczynał od opisania jaki problem ma rozwiązywać kod, a dopiero potem jaki problem ma twoje rozwiązanie.

Nie ma wątpliwości, że coś parsujesz.
Pokazałeś nam elementy drzewa AST.
Teraz buildAST pasuje do elementu drzewa jak pięść do oka i zapewne to jest źródłem twoich problemów.
To co iteruje po tokenach powinno tworzyć drzewo AST, a nie że to drzewo tworzy samo siebie. Drzewo nie powinno mieć pojęcia, że istnieje coś takiego jak parser i tokeny. Parser ma wyłuskać tokeny, a potem na podstawie tokenów tworzone jest drzewo AST.

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