Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem C++ Alokacia a dealokacia pamati

Caute ucim sa C++ sorry za zaciatocnicke otazky ale rad by som si par veci ujasnil.

V C++ si programator moze zvolit kde alokuje pamat, ci na stacku alebo na halde. takze prva otazka:

1. kedy zvolit stack a kedy heap?
2. Dalsia vec chcem si ujasnit aky je rozdiel medzi tymito 3omi instanciaciami objektov?

auto objekt1 = Trieda();
objekt1.Metoda();
 
auto objekt2 = new Trieda();
objekt2->Metoda();
 
auto objekt3 = &Trieda();
objekt3->Metoda();

Prvy vytvara objekt na stacku. Druhy na halde a treti tiez na halde? Takze druhy a treti zapis je eqvivalentny?

3. kedy uvolnovat pamat? Ako zabranit tomu aby nastali memory leaky. Odkedy sa ucim C++ tak som zatial na ziadny problem nenarazil a to vobec nevolam delete. Takze aj v C++ sa uvolnuje pamat automaticky? Kedysi som programoval v Delphi a tam sa kazdy objekt musel uvolnit rucne procedurou Free() inak spadla cela aplikacia, take nieco sa mi v C++ este nestalo, preco?

4. kedy pouzit shared_pointery

5. aku knihu o C++ mi viete doporucit? Idealne aby bola podrobna, aktualna (C++11).

Jsou zobrazeny jen nové odpovědi. Zobrazit všechny
Předmět Autor Datum
MM: Vdaka za odpovede ale mam v tom este vacsi gulas. Pisal si ze ten treti zapis je zly, ale sprav…
mikser 02.02.2014 13:19
mikser
Pouzivanie auto je totalne nebezpecna zhovadilost ptz tym odstavujes najdolezitejsiu vyhodu C, a to…
MM.. 02.02.2014 13:23
MM..
Ale ved o automaticke odvodzovanie typov sa stara prekladac, takze ta typova kontrola tam stale je.…
mikser 02.02.2014 13:39
mikser
ale neni to mozno presne ten typ ktory si chcel. 5 moze byt char, unsigned char, int unsigned int, i…
MM.. 02.02.2014 13:52
MM..
alebo ina vec x=10; x+=3000000000; if(x>15) printf("spravne"); else printf("nespravne"); a skus si… nový
MM.. 02.02.2014 13:54
MM..
1. Stack volíš vtedy, keď nepotrebuješ, aby tá trieda žila dlhšie. Heap zasa v tých ostatných prípad…
los 02.02.2014 13:20
los
BTW. ak pominiem to hardcore s tym iteratorom, ty by si napisal namiesto Motorka x; auto x = Motorka…
MM.. 02.02.2014 13:36
MM..
V tomto prípade by som to napísal normálne. Ale tie iterátory sú pre auto ako stvorené.
los 02.02.2014 13:43
los
Je to mozne, ja som konzerva, taketo veci ma zasadne ani nenapadnnu (a napr. na poslednu vec ktoru s… nový
MM.. 02.02.2014 14:07
MM..
To sa nedá tak, že deklaruješ iba auto y. Musí sa použiť initializer, aby bolo z čoho ten typ možné… nový
los 02.02.2014 14:55
los
auto y = NULL; Fcia1(y); :-) Ja viem bude asi error (y bude void* alebo int?), ale ako spravna konz… nový
MM.. 02.02.2014 16:15
MM..
y bude int. void* by to bol vtedy, ak by si spravil "auto y = nullptr". Keď robíš klasické pretypov… nový
los 02.02.2014 16:51
los
si predstav strukturu struct tralala { struct tramtaram x; int dalsi; } struct tramtaram { int dalsi… nový
MM.. 02.02.2014 17:16
MM..
BTW. nepoznal som to (ja som zakysol u MS 2009), takze vdaka za objasnenie pouzitia napr. u tych ite… poslední
MM.. 02.02.2014 17:30
MM..

MM:

Vdaka za odpovede ale mam v tom este vacsi gulas. Pisal si ze ten treti zapis je zly, ale spravil som si testovaciu applikaciu a ono mi to funguje:

#include <iostream>
#include <cstring>

using namespace std;

class Trieda
{
public:
	void Metoda(wstring input)
	{
		wcout << input.c_str() << endl;
	}
};


void main()
{
	auto objekt1 = Trieda(); // ekvivalent Trieda objekt;
	objekt1.Metoda(L"Objekt alokovaný na stacku");
	auto objekt2 = new Trieda();
	objekt2->Metoda(L"Objekt alokovaný na heape");
	auto objekt3 = &Trieda();
	objekt3->Metoda(L"Objekt alokovaný na ???");
	system("pause");
}

Akurat som sa mylil v tom ze ten treti zapis je eqvivalentny tomu druhemu. Nie je podla vsetkeho sa asi vytvara na stacku a do premennnej sa uklada referencia na tento objekt.

Viem co znamena auto je to keyword z C++ 11 pouziva sa pri type inference to iste ako keyword var v C#, v tomto pripade na sprehladnenie zdrojaku. Viem ze takyto zdojak nebude kompatibilny so starsimi verziami C++ ale ja uz kompatibilitu so starsimi verziami ani neriesim chcem sa naucit novy standard so vsetkymi featurami ako lambdy atd.

a o shared pointeroch sa pise napriklad tu: http://babel.blog.root.cz/2012/04/11/sprava-pameti -v-c/ vraj sa pri ich pouziti nemusim starat o uvolnovanie pamate, pretoze sa pouzije pocitadlo referencii.

Pouzivanie auto je totalne nebezpecna zhovadilost ptz tym odstavujes najdolezitejsiu vyhodu C, a to je typova kontrola. Navyse doraz sa kladie vzdy na prenositelnost kodu, ptz visal MS nejaka hovadina 2010 zajtra moze prestat existovat :D A pozajtra pride sef a povie ti ze potrebuje ten program pre linux.

Treti zapis je poniter na funkciu, co je uplny nezmysel ak neexistuje ovjekt.

ale neni to mozno presne ten typ ktory si chcel. 5 moze byt char, unsigned char, int unsigned int, int64, apod.
Rozdiel medzi signed a unsigned je totalne zasadny, napr. urob si program
x=10;
x-=20;
if(x<5) printf("spravne");
else printf("nespravne");

a skus si to s x signed a unsigned. A auto bude teda co? Typy a typova kontrola je extremne dolezita vec. Ak by si napr. pri if mixoval signed a unsigned dostanes warning apod.

alebo ina vec
x=10;
x+=3000000000;
if(x>15) printf("spravne");
else printf("nespravne");

a skus si to s auto na 32bitovom prekladaci.

P.S> Narazam na to ze pri alokacii premennej je ZASADNA vec jaku bude mat v pamati reprezentaciu, a to ma posudit programator ze jaku reprezentaciu tam chce mat (kvoli limitnym hodnotam a pouziti danej premennej apod). Neda sa to nechat na prekladac (a ak ano tak to je nebezpecne ptz programator nepouzil mozog a limity su nahodne a programator ani nevie jake su tie limity)
P.S> napr. pri praci s offsetmi suborov je unsigned kriticky, a kontroluje sa to aj u parametrov volani fcii, apod. S auto tam budes mat neco. A mozno dostanes aj warning. Truba bude ignorovat aj warning, hlavna vec ze pouzil auto.

1. Stack volíš vtedy, keď nepotrebuješ, aby tá trieda žila dlhšie. Heap zasa v tých ostatných prípadoch.

2a. Inštancia objekt1 je alokovaná na stacku. Po opustení bloku je automaticky uvoľnená.
2b. Inštancia objekt2 je alokovaná v heape. Po opustení bloku zostáva v pamäti.
2c. Inštancia triedy je alokovaná na stacku, pričom v objekt3 je uložený smerník na túto inštanciu. Po opustení bloku je inštancia uvoľnená.

3. Pamäť uvoľňuješ vtedy, keď už s daným objektom nepotrebuješ pracovať. V C++ sa pamäť uvoľňuje automaticky len v prípade, že je objekt na stacku. Ak alokuješ v heape, tak musíš uvoľňovať podobne ako v Delphi.

4. shared_ptr použiješ vtedy, keď chceš, aby sa inštancia automaticky uvoľnila vtedy, keď ju už nikto nepoužíva. Vďaka počítaniu referencií sa pamäť uvoľní automaticky. Je to v podstate to isté, ako interfejsy v Delphi.

Kľúčovému slovu auto by som sa vôbec nevyhýbal. Namiesto zápisov typu "std::map<std::string, std::map<std::string, std::string> >::iterator it" vo for cykloch použiješ "auto it". V C++ by som práveže uprednostňoval všetky štandardné vlastnosti jazyka, ako sú shared_ptr, unique_ptr, move constructory a podobne. Keď to zvláda VS2013 a gcc, tak nie je čo riešiť.

BTW. ak pominiem to hardcore s tym iteratorom, ty by si napisal namiesto
Motorka x;
auto x = Motorka();
?
2x viac pismen. Navyse je to matuce a nejasne (neviem okamzite ci to Motorka() je trieda alebo nejak funkcia o 3 strany dalej alebo jakeho svateho vynalez. Mysli aj na toho kto to bude citat o rok po tebe... :)

Je to mozne, ja som konzerva, taketo veci ma zasadne ani nenapadnnu (a napr. na poslednu vec ktoru som robil pred rokom na VC++ bola aby to slo aj na Win98 :). S novymi MS kravinami compilermi ti ten vytvor nepojde ani na XP, nie to este na 98 :)
Neviem ci tam je kriticke jaky typ pouzijes u iteratoru, ja by som sa vyhol aj samotnemu iteratoru a robil to nejak konzervativne :D Ok to je fuk. Este ma napada dalsia vec, a to je overloaded funkcie, povedzme ze mam
Fcia1(int* a);
Fcia1(char* a);

int x;
Fcia1(&x); // pohoda

auto y;
Fcia1(&y); // ?????

:)

auto y = NULL;
Fcia1(y);

:-) Ja viem bude asi error (y bude void* alebo int?), ale ako spravna konzerav povazujem zavadzanie takychto noviniek za silnu zhovadilost. Problem je v tom ze ak pisem funkciu tak pri klasickom sposobe mam kontrolu nad tym co robim, a v pripade ze cudzia fcia vracia nieco ine dostatnem error.
Napr.
int x; // chcem robit s int
x=CudziaFunkcia(); // ak nevracia int ale napr. int* tak dostanem error apod
auto x=CudziaFunkcia(); // nedostanem error, neviem s cim vlastne pracujem, aj ked sice mozem dostat error dalej, ale ak napr. pri low level veciach pretypujem hned x napr na int* ptz chcem pristupit na adrtesu ktoru mi vratil niekto ako cislo, nedostatem error ziaden. Apod. Je to odstranenie urcitej kontroly, ak napr. ak je gulas vo funkciach a niekto updatuje cudzie funkcie tak ze vracaju nieco ine apod. Ano da sa to povazovat aj ako vyhoda ze hura ked updatujem cudziu funkciu ze bude vracat nejaku inu nemusim prepisovat aj volajuce funkcie, ale nemusi to byt vzdy bezpecne to pouzivat. Nech si na to dava radsej pozor.

si predstav strukturu
struct tralala
{
struct tramtaram x;
int dalsi;
}
struct tramtaram
{
int dalsi;
int predosly;
}

A ty sa pomylis a myslis si ze fcia vracia struc tralala, ale ona vracia struct tramtaram. Ked pouzijes
auto x = DajStrukturu();
tak si tu chybu vobec nevsimnes, ptz ak urobis if(x->dalsi == NULL) neco tak nedostanes ziaden error.
Ak by som ale jasne napisal co si myslim ze tam chcem dostat
struct tralala *x;
x = DajStrukturu();
tak dostamen error od compilera s textom "ty trubka ta funkcia vracia pointer na tramtaram, daj si kafe a kukaj poriadne". Kontroly su na to aby odhalovali chyby programatora, a nie na to aby sa v dalsej verzii nahradili nejakym skvelym auto pre debilov co prechadzaju z visualbasicu :) Ja len vysvetlujem preco mi to auto je proti srsti, netvrdim ze to je uplne nepouzitelne ale hlavne novacikom by som ruky olamal keby mi to pouzivali aj na obycajne int (len sranda :-))

Zpět do poradny Odpovědět na původní otázku Nahoru