Pomożecie wytłumaczyć mi co tu sie dzieje?

0

Ucze się c++ i obecnie przerabiam struktury, które dosyć rozumiem, ale nie rozumiem jednej rzeczy tu.

Dlaczego program wyświetli x=5 a nie 10? Na początku mialem taki zamysł, że to void i nic nie zwraca bo wcześniej czytałem że struktury, jeżeli się ich nie wywoła to sporządzą tylko samą kopie danych i nic nie zwrócą (jakoś tak). Jednak po przerobieniu voida na int problem się nie rozwiązuje. Pomożecie mi to zrozumieć?

#include <iostream>

using namespace std;

struct MojaStruktura
{
	int x;
};

void AktualizujStrukture(MojaStruktura moja_struktura)
{
	moja_struktura.x = 10;

}

int main()
{
	MojaStruktura moja_struktura;
	moja_struktura.x=5;
	AktualizujStrukture (moja_struktura);
	cout << moja_struktura.x;

	return 0;
}

1

Bo przekazujesz do funkcji przez wartość, w funkcji tworzona jest kopia :)

0
au7h napisał(a):

Bo przekazujesz do funkcji przez wartość, w funkcji tworzona jest kopia :)

Możesz bardziej szczegółowo bo średnio rozumiem?

0

Zanim się zabierzesz za struktury Bracie sprawdź w góglach frazy:

  • c++ przekazywanie parametru funkcji przez wartość
  • c++ przekazywanie parametru funkcji przez referencję/wskaźnik
    wtedy wyjaśni się tajemnica, co tam się dokładnie w twym kodzie stało. A jest to rzecz taka dosyć elementarna, która raczej blokuje pójście dalej z nauką.
0
MasterBLB napisał(a):

Zanim się zabierzesz za struktury Bracie sprawdź w góglach frazy:

  • c++ przekazywanie parametru funkcji przez wartość
  • c++ przekazywanie parametru funkcji przez referencję/wskaźnik
    wtedy wyjaśni się tajemnica, co tam się dokładnie w twym kodzie stało. A jest to rzecz taka dosyć elementarna, która raczej blokuje pójście dalej z nauką.

Powiedz to autorowi książki, z której sie ucze :)

0
twonek napisał(a):

Przekazywanie parametru przez wartość i referencję

Wiem jak działa przekazywanie parametru tylko nie wiem dlaczego w strukturach to nie działa tak jak normalnie. Zmieniłem kod na taki:

#include <iostream>

using namespace std;

struct MojaStruktura
{
    int x;
};

int AktualizujStrukture(MojaStruktura moja_struktura)	//void zamieniłem na int
{
    moja_struktura.x = 10;
    return moja_struktura.x;				//return, czyli "teoretycznie" powinno zwrócić nową wartość

}

int main()
{
    MojaStruktura moja_struktura;
    moja_struktura.x=5;
    AktualizujStrukture (moja_struktura);
    cout << moja_struktura.x;

    return 0;
}

Struktury są inaczej zrobione? Panują tam inne zasady czy ja po prostu czegoś oczywistego nie rozumiem?

Bo operacje na normalnych funkcjach są dla mnie oczywiste. Na przykład to: https://www.p-programowanie.pl/cpp/przekazywanie-argumentow-do-funkcji-c/

Rozumiem to, pomijając przekazywanie argumentów przez wskaźnik i referencje ale to dlatego że się nie zgłębiałem w ten temat. Na razie wystarczy mi podstawa podstaw.

Tak przy okazji to wskaźniki mam następne w książce.

2

Taki zapis:

void AktualizujStrukture(MojaStruktura moja_struktura) {
    // ...
}

oznacza, że funkcja tworzy kopię przekazanego argumentu na swój użytek i po dotarciu do swojego końca wyrzuca go do śmieci. Żadna zmiana na moja_struktura nie jest widoczna w main, bo funkcja operuje na swojej własnej kopii.

Taki zapis:

void AktualizujStrukture(MojaStruktura& moja_struktura) {
    // ...
}

Oznacza, że operujesz na referencji (z grubsza biorąc, innej nazwy) zmiennej, zatem zmiany zostaną wprowadzone tak jak sobie życzysz.

Taki zapis

void AktualizujStrukture(MojaStruktura* moja_struktura) {
    // ...
}

Oznacza, że dostajesz adres swojej zmiennej, więc również możesz się do niej dobrać bezpośrednio i ją pozmieniać, ale przy wywoływaniu zamiast zmiennej podajesz jej adres - AktualizujStrukture (&moja_struktura); zamiast AktualizujStrukture (moja_struktura);.

Zwracanie argumentu nie ma tu nic do rzeczy.

0
Spearhead napisał(a):

Taki zapis:

void AktualizujStrukture(MojaStruktura moja_struktura) {
    // ...
}

oznacza, że funkcja tworzy kopię przekazanego argumentu na swój użytek i po dotarciu do swojego końca wyrzuca go do śmieci. Żadna zmiana na moja_struktura nie jest widoczna w main, bo funkcja operuje na swojej własnej kopii.

Taki zapis:

void AktualizujStrukture(MojaStruktura& moja_struktura) {
    // ...
}

Oznacza, że operujesz na referencji (z grubsza biorąc, innej nazwy) zmiennej, zatem zmiany zostaną wprowadzone tak jak sobie życzysz.

Taki zapis

void AktualizujStrukture(MojaStruktura* moja_struktura) {
    // ...
}

Oznacza, że dostajesz adres swojej zmiennej, więc również możesz się do niej dobrać bezpośrednio i ją pozmieniać, ale przy wywoływaniu zamiast zmiennej podajesz jej adres - AktualizujStrukture (&moja_struktura); zamiast AktualizujStrukture (moja_struktura);.

Zwracanie argumentu nie ma tu nic do rzeczy.

Ok, zaczynam rozumieć. Pytanie: Czy w ogóle można zwrócić wartość z kopii nie licząc wskaźników i referencji? Tak z ciekawości pytam.

0

Ok, zaczynam rozumieć. Pytanie: Czy w ogóle można zwrócić wartość z kopii nie licząc wskaźników i referencji? Tak z ciekawości pytam.

Kopia w ciele funkcji to taka sama zmienna jak każda inna, możesz z nią robić co ci się podoba:

#include <iostream>

struct MyStruct {
    int x;
};

MyStruct function(MyStruct s) {
    s.x = 2;
    return s;
}

int main() {
    MyStruct s{1};

    s = function(s);

    std::cout << s.x;
}

W tym kodzie zwracam przez wartość, zatem teoretycznie tworzę kopię kopii. Ponieważ jednak istnieje optymalizacja o nazwie RVO, przy zwracaniu nie zajdzie dodatkowe kopiowanie, co poprawia wydajność.

Trzeba jedynie pamiętać, że kopia jest automatycznie niszczona przy wyjściu z funkcji. Popatrz na ten przykład:

#include <iostream>

struct MyStruct {
    int x;
};

MyStruct* function(MyStruct s) {
    return &s;
}

int main() {
    MyStruct s;
    MyStruct* sp;

    sp = function(s);

    std::cout << sp->x;
}

Zwracam adres kopii utworzonej w funkcji function(). Ponieważ zaś kopia zostaje usunięta po wyjściu z funkcji, próba dobrania się do niej poprzez zwrócony wskaźnik oczywiście się nie powiedzie i cały program eksploduje z błedem Segmentation Fault.

0

Dzięki wszystkim za wytłumaczenie :)

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