Zwracanie wskaźnika

0

nie wiem czy dobrze zadam pytanie ale rozpatrzmy taką hipotetyczną sytuację w programie

class MyClass
{
public:
    int *funkcja();
};

int *MyClass::funkcja()
{
    static int z=0;
    cout << "w klasie MyClass z = " << z << endl;

    return &z;
}

int main()
{
    MyClass *wsk1, zmienna;

    wsk1=&zmienna;

    int *wsk2;

    wsk2=wsk1->funkcja();

    *wsk2=987;

    wsk1->funkcja();

    return 0;
}

funkcja w klasie zwraca adres i ten adres przypisuję do wskaźnika i następnie za pomocą wskaźnika modyfikuję zawartość

pytanie jest takie - czy ta technika do czegoś może się przydać ? O ile można nazwać to techniką czy brzydkim oszustwem ?
drugie pytanie jest takie - czy jest sens deklarować zmienne jako static ? Jeżeli tak, to kiedy to się może przydać ?

4

To jest stan globalny, który się zmienia w niekontrolowany sposób.
Efekt jest taki, że im więcej używa się tej funkcji tym trudniej utrzymywać ten kod.
Jest wiele alternatywnych rozwiązań, które nie mają tych wad. Wybór zależy od szczegółów, co to właściwie ma robić.

Taką formę kodu odrzuciłbym na review i domagałbym się od autora alternatywnej metody lub naprawdę bardzo dobrego uzasadnienia, czemu ma być to potraktowanie wyjątkowo.

1

Gratulacje wymyśliłeś "anty"-wzorzec singleton, który w C++ raczej zapisuje się w ten sposób:

#include <iostream>
using namespace std;

class Global
{
	public:
	struct Values
	{
		int a;
		string b;
		Values(int a=0,const string &b=""):a(a),b(b) {}
	};
	Values *operator->()
	{
		static Values values;
		return &values;
	}
};

void set()
{
	Global()->a=13;
	Global()->b="Ala ma kota";
}

void get()
{
	cout<<"a="<<Global()->a<<';'<<endl;
	cout<<"b="<<Global()->b<<';'<<endl;
}

int main ()
{
	set();
	get();
    return 0;
}

Wszyscy psioczą na ten wzorzec ale totalnie bez sensu, bardzo łatwo i tanio przekształca się w Property:

#include <iostream>
#include <unordered_map>
using namespace std;

class Global
{
	private:
	string key;
	public:
	Global(const string &key=""):key(key) {}
	struct Values
	{
		int a;
		string b;
		Values(int a=666,const string &b="default"):a(a),b(b) {}
	};
	Values *operator->()
	{
		static unordered_map<string,Values> map;
		return &map[key];
	}
};

void set(const string &key="")
{
	Global(key)->a=13;
	Global(key)->b="Ala ma kota";
}

void get(const string &key="")
{
	cout<<"a[\""<<key<<"\"]="<<Global(key)->a<<';'<<endl;
	cout<<"b[\""<<key<<"\"]="<<Global(key)->b<<';'<<endl;
}

int main ()
{
	set();
	get();
	get("alt");
    return 0;
}

Po czym nadal można korzystać z:
Global()->a i Global()->b
A tam gdzie trzeba to używamy ustawień specyficznych.

3

Zacznę od końca, taki kod może mieć sens TYLKO jeśli zmienna z jest static, bo inaczej będzie alokowana na stosie. W związku z czym, jeśli zostanie nadpisana, w pewnych sytuacjach może napsać stan innej funkcji, nawet prowadzić do wysypania programu, jeśli przypadkiem przez ten wskaźnik nadpiszesz jakiś kod powrotu czy bajt zerowy stringa. W każdym razie, może się wydawać przez jakiś czas, że wszystko jest OK i powodować czasem, trudne do zdiagnozowania problemy.

Piszę to głównie, żeby pobudzić wyboraźnię, bo ani zwracanie takiego wskaźnika na statyczną zmienną lokalną, ani w ogóle używanie zmiennych statycznych lokalnych, raczej nie powinno być używane. Raczej trudno znaleźć dla tego racjonalne zastosowanie, bo ich użycie sprawia, że funkcja nie będzie wielobieżna, a dodatkowo niepotrzebnie wprowadzasz stan, bądź co bądź, globalny (w przypadku ze wskaźnikiem). Nie mylić ze zmiennymi globalnymi i funkcjami, dla nich ten modyfikator ma inne znaczenie (sprawia że taka funkcja czy zmienna nie jest dostępna poza danym modułem); w ich przypadku jest pożądany, jeśli ma zastosowanie.

2

Panowie obserwowałem tematy kubińskiego przez ostatnie dni. Powiem wam dajcie spokój bo on traktuje to nie jako platformę to rozwiązywania problemów a ko repetytorium dla wszystkiego(mentoring za darmo). Niech gość przyjdzie z konkretnymi problemami a nie tym że książek nie czyta,
To się nie skończy bo zaraz odkryje smart pointery i będzie pytanie o coś takiego(i nie zdziwie się że na to wpadnie)

class MyClass
{
public:
    std::shared_ptr<int> funkcja();
};

std::shared_ptr<int> MyClass::funkcja()
{
    std::shared_ptr<int> z = std::make_shared<int>(7);
    cout << "w klasie MyClass z = " << z << endl;

    return z;
}

int main()
{
    MyClass *wsk1, zmienna;

    wsk1=&zmienna;

    int *wsk2;

    wsk2=wsk1->funkcja();

    *wsk2=987;

    wsk1->funkcja();

    return 0;
}

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