- Karácsonyfaként világíthat a Thermaltake új CPU-hűtője
- Az USA vizsgálja a RISC-V kínai terjedésének kockázatát
- Kicsit extrémre sikerült a Hyte belépője a készre szerelt vízhűtések világába
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Kihívás a középkategóriában: teszten a Radeon RX 7600 XT
- Azonnali informatikai kérdések órája
- Egészen nagy teljesítményspektrumon fedné le a mobil piacot az AMD
- Milyen asztali (teljes vagy fél-) gépet vegyek?
- Autós kamerák
- Intel Core i5 / i7 / i9 "Alder Lake-Raptor Lake/Refresh" (LGA1700)
- Gaming notebook topik
- Milyen videókártyát?
- Házimozi haladó szinten
- Milyen TV-t vegyek?
- VR topik (Oculus Rift, stb.)
Hirdetés
-
Kicsit extrémre sikerült a Hyte belépője a készre szerelt vízhűtések világába
ph A cég megoldása centralizált vezérelhetőséggel, masszív radiátorral és robusztus ventilátorokkal igyekszik vásárlásra csábítani.
-
Dragon Ball: Sparking! Zero - Mester és tanítvány
gp Egyelőre még mindig nem kaptunk megjelenési dátumot a játékhoz.
-
Toyota Corolla Touring Sport 2.0 teszt és az autóipar
lo Némi autóipari kitekintés után egy középkategóriás autót mutatok be, ami az észszerűség műhelyében készül.
Új hozzászólás Aktív témák
-
jattila48
aktív tag
válasz PandaMonium #4086 üzenetére
Szerintem meg azt sem érted, hogy pontosan miről is van szó. target-tel nem fv. pointert kapsz vissza, hanem annak az objektumnak a címét, amit az std::function-ban eltároltál (ha ez történetesen fv. pointer volt akkor azt, ha std::bind volt akkor azt). A target template argumentumában pontosan meg kell adni az std::function-ben eltárolt callable object típusát, különben NULL-t kapsz vissza ([link] . Lambdát ugyan lehet megfelelő fv. pointerré konvertálni, de csak akkor ha nem kapturál semmit (ez számomra érdektelen). Szóval előbb olvass, értelmezz és ne az észt oszd!
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
-
jattila48
aktív tag
válasz dobragab #4087 üzenetére
Köszi szépen a válaszodat. Először is engedd meg, hogy egy hibát javítsak:
static RET fptr_handler(ARGS... args)
{
tl_function(std::forward<ARGS>(args)...);
}helyesen:
static RET fptr_handler(ARGS... args)
{
return tl_function(std::forward<ARGS>(args)...);
}Egyébként szép megoldás a problémára.
Lényegében hasonló, mint amit a szimulációban írtam. Ott globálisan hoztam létre az objektumokat, ezek tfv.-eit pedig free wrapper fv.-eken keresztül hívtam meg (amik a globális objektumokhoz hozzáférnek), és a free fv.-ekre mutató fv. pointert tudom aztán használni callback fv. pointerként.
Lényegében a te megoldásod is hasonló, csak nem globális, hanem (thread_local) static std::function objecteket hozol létre (tl_function), amik tartalmazzák az objektum címét (ez a lambdában kapturált argumentum), és a megfelelő tfv. pointert. Majd ezt a tl_function std::function objectet meghívó fptr_handler statikus wrapper tfv.-nek a címét (mint közönséges pattintott C fv. pointert) adod vissza. A trükk pedig az, hogy a to_fptr function template második argumentuma egy []{} dummy lambda, aminek a típusa mindíg (fordító által generált) egyedi típus, ezért a to_fptr_t class template minden egyes alkalomkor külön-külön példányosul (a dummy lambda aktuális típusával), minden egyes function object-re külön osztályt, és azzal külön fptr_handler fv.-t létrehozva. Szép megoldás, gratula!„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz EQMontoya #4106 üzenetére
Melyik ostoba hozzászólásomra gondoltál? Amiben annak minősítettem, hogy szerinted 2018-ban a bináris api fv.-eknek C++ template-eket kéne tudni értelmezni? Ha az szerinted nem volt ostobaság, az baj.
A másik, hogy nincs azzal baj, ha api fv.-eket akarok objektum orientált módon használni, az miért ostobaság? Ilyen simán előfordulhat. Az, hogy te még nem találkoztál ilyennel, nem jelent semmit.[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
dobragab
addikt
válasz EQMontoya #4103 üzenetére
Egyébként ezt is meg lehet csinálni, azért élőben is szoktad látni a próbálkozásaimat
Annyi a lényeg, hogy a szüzet a másik irányból kell támadni. (Mármint a legelvadultabb C++ kiskapukat kell keresgélni és abuse-olni.) Ami szar meló, sok munka van vele, és sose lesz az igazi
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
dobragab
addikt
válasz Ereshkigal #4110 üzenetére
Én is erre próbáltam utalni, csak finomabban
Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
Dinter
addikt
Valaki tudna segíteni, hogy ebben miért van memóriaszivárgás? [link]
Tuti, hogy a ListaElem-ek azok, viszont amikor törölni akarnám őket, azt írja, hogy "nem létező adat felszabadítása".
-
xors
senior tag
Sziasztok!
Valaki el tudná nekem mondani, hogy ennél a konstuktornál (generikus tömbhöz van), miért fontos a "T()" ?template<class T, size_t maxsiz = 6>
class Array {
size_t siz; // adatok tényleges mennyisége
T t[maxsiz]; // elemek tömbje
public:
/// default konstruktor
explicit Array(size_t n = 0, const T& value = T() ) : siz(0) {
while (siz < n && siz < maxsiz)
t[siz++] = value;
}
}; -
-
xors
senior tag
válasz EQMontoya #4115 üzenetére
Igen, erre én is gondoltam, csak az zavart meg, hogy a típusnév(), ugye konstruktor hívás, aminek nincs visszatérési értéke alapból.
De azt értem , hogy kell valami default érték, amit ugye majd a sablon fog adni, és a default konstruktor pedig valamit létre tud hozni. -
Dinter
addikt
Valaki tudna segíteni, hogy miért kétszer olvas be ez a függvény?
bool beolvas(){
String nev;
int letszam;
String str1;
String str2;
int adat;
int konstr; //csapat típusa
std::ifstream in("adatok.txt");
while((in>>konstr)){
cout<<"KONST:"<<konstr<<endl;
switch(konstr){
case 1:{
in>>nev;
in>>letszam;
in>>str1;
in>>str2;
Focicsapat* uj= new Focicsapat(nev, letszam, str1, str2);
hozzaad(uj);
break;
}
case 2:{
in>>nev;
in>>letszam;
in>>adat;
Kezicsapat* uj= new Kezicsapat(nev, letszam, adat);
hozzaad(uj);
break;
}
case 3:{
in>>nev;
in>>letszam;
in>>adat;
Kosarcsapat* uj= new Kosarcsapat(nev, letszam, adat);
hozzaad(uj);
break;
}
default:
break;
}
}
in.close();
return true;
}Input:
1 BME Foci 22 Egyik Edzo Masik Edzo
2 BME Kezi 15 2000000
3 BME Kosar 11 8 -
Headless
őstag
Sziasztok!
Viszonylag új vagyok a c++ programozásban és biztos, hogy nem a helyes úton járok annak megtanulásában/értésében. De most ezt dobta a gép, van egy struktúrám amibe pointerek és dupla pointerek vannak. azt szeretném kérdezni, hogy hogy tudnám megtudni a dupla pointerek nagyságát, hogy egy for ciklussal végig mehessek rajtuk?
typedef struct {
...
API_AddParType **params;
...
} API_ElementMemo
typedef struct {
...
char name[API_NameLen];
....
} API_AddParType;tehát ami most megy
memo.params[0]->name
tehát a 0. paraméter nevét kiadja. hogyan tudom kiolvasni, hogy hány paraméterrel rendelkezik?
LEDE - R3G/DIR860l -> https://tinyurl.hu/Ntkb/
-
dabadab
titán
válasz Headless #4121 üzenetére
"hogyan tudom kiolvasni, hogy hány paraméterrel rendelkezik?"
Sehogy. Alapvetően két dolgot tudsz csinálni:
1. valahogy átadod a pointertömb mellé azt is, hogy hány eleme van
2. (és ez a javasolt) hagyod a C-s tömbökét és C++-ban C++-ban programozol, ami jelen esetben azt jelenti, hogy az STL konténerei közül használsz valamit, pl. vectort.DRM is theft
-
Headless
őstag
válasz dabadab #4122 üzenetére
Köszönöm a gyors választ.
Ahogy az kitalálható volt a definicióból ez egy API részlet, tehát fő programba nem tudok belenyúlni. Ezt kell használni, közben megtaláltam az API-ban azt a funkciót ami a paraméterek információit tartalmazza így meglett ez a probléma, de valahogy olyan mintha nem tudnám kiolvasni a 0-án kívüli elemeket. De valószínű ezzel már egy inkább specifikus fórumban kéne feltennem a kérdést.
LEDE - R3G/DIR860l -> https://tinyurl.hu/Ntkb/
-
Headless
őstag
válasz Headless #4123 üzenetére
A korábbi gondom megoldódott, viszont most inkább felétek való kérdésem lenne.
van egy karakter tömböm
char name[32]
nem én csináltam ez van megadva
és van egy (ezt úgy módosíthatom ahogy akarom)
const char *paramNames[4]={"ConPosX_1","ConPosY_1","ConPosX_2","ConPosY_2"};
tömböm és össze kellene hasonlítani a kettőt ha megegyezik, akkor kéne vele csinálnom valamit.
Namár most ha így szimplán if-be rakom őket nem fog megegyezni.
if(name==paramNames[i])
Próbáltam hogy a tömbömet valami olyasmi formában hozom létre, hogy
char paramNames[4][32];
paramNames[0]="ConPosX_1";csak így meg nem tudja a char [10]-et char[32]-be alakítani. Hogy kellene ezt helyesen megoldani?
Hú de el vagyok veszve itt a string/char, mutató tömbökkel sajnos ost jön elő, hogy nem vagyok képben ezekkel, próbáltam keresgélni, de sajnos nem találtam megfelelő megoldást.
LEDE - R3G/DIR860l -> https://tinyurl.hu/Ntkb/
-
xors
senior tag
válasz Headless #4124 üzenetére
char* összehasonlításra ott a strcmp(const char* egyik, const char* masik) függvény. Ez tulajdonképpen a C string.
A tömböd jó úgy ahogy csináltad, const char* paramNames[4] = {//elemek}
Természetesen a char* -ok tömbjét (paramNames) végig kell nézned egyesével egy for ciklussal.Én ilyesmit csinálnék:
#include <string.h> //a strcmp -hez kell
for(int i = 0; i< 4; i++)
if(strcmp(name, paramNames[i])
//itt azt csinálsz amit akarsz velük, ekkor egyeznek megremélem tudtam segíteni
[ Szerkesztve ]
-
Z_A_P
addikt
-
Headless
őstag
Hát mint írtam a name az nem char * hanem fix hosszúságú char [32] ha ez mindegy akkor most csak annyiban vagyok elakadva, hogy az
'strcmp_DISABLED' : undeclared identifier
hibát kapom, valahol engedélyeznem kéne, kell valami include hozzá <string>-en kívül?LEDE - R3G/DIR860l -> https://tinyurl.hu/Ntkb/
-
xors
senior tag
válasz Headless #4127 üzenetére
a char[32], az ugyanúgy egy char* mutató, csak foglalva van hozzá 32db hely a memóriában.
A méret igazából csalóka mert lehet röviebb is mint a lefoglalt, stringek esetén az utolsó karakter utáni lezáró nulla ('\0') jelzi a végét, a strcmp is ezt használja.
A hiba arra utal, hogy valamiért a strcmp ki van kapcsolva, esetleg próbáld meg az#include <cstring>
std::strcmp(egyik, masik)ha így sem megy, akkor kell írni egy összehasonlító függvényt, az nem egy nagy cucc
int myStrCmp (const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
while (*p1 != '\0') {
if (*p2 == '\0') return 1;
if (*p2 > *p1) return -1;
if (*p1 > *p2) return 1;
p1++;
p2++;
}
if (*p2 != '\0') return -1;
return 0;
} -
Teasüti
nagyúr
Sziasztok!
Volna egy kezdő kérdésem, tudnátok segíteni kérlek?
Köszi! -
dobragab
addikt
Az, hogy a masodik kodreszlet nem szabvanyos, csak C-ben, C99-tol, C++-ban sose volt az. Egyebkent a neve Variable Length Array.
Az elsovel pedig az a baj, hogy a
delete[]
-et konnyu elfelejteni (vagy nem figyelni valami aprosagra, ami miatt nem fut le, hiaba irtad ki, pl.return
vagy kivetel), sulyos hibaforras.Hasznalj helyette
std::vector
-t, esetleg teddstd::unique_ptr
-be, ha a vector tul "nagy" (arduino-n nem tudom mik vannak).Tudom, tudom, akasszak a tökömre egy lámpát, hogy sötétben is tudjak kaszálni.
-
-
dabadab
titán
válasz Teasüti #4132 üzenetére
"Még sose alkalmaztam new-t. Mi szükségem volna rá, ha meg tudom oldani lokális változókkal?"
Ha meg tudod oldani, akkor semmi Akkor van rá szükséged, ha nem tudod megoldani lokális változókkal (pl mert azt a p[] tömböt visszatérési értékként akarod használni a függvényedben).
DRM is theft
-
mgoogyi
senior tag
válasz Teasüti #4132 üzenetére
A new meg nem new között az a különbség, hogy a new-val a heap-en foglalsz memóriát, new nélkül meg a stack-en. (itt nem erre a nem szabványos dologra gondolok:
int p [I]= {};
)
Ez utóbbi elég limitált tud lenni, ha majd egyszer írsz rekurzív(önmagát hívó) függvényt, belefuthatsz.
Ezt hívják stackoverflow-nak. Olvass utána, hogy mi az a heap és mi az a stack.
Egyébként paraméterezett méretű tömböt new nélkül nehéz lértehozni.A new (new []) esetében egy pointer-t kapsz vissza és a te feladatod ezt eltakarítani delete-tel ( delete []).
Azért, hogy ezt ne felejtsd el, javasolt olyan osztályokat használni, amik megteszik ezt helyetted.
A vector meghívja helyetted a new[]-t és a delete[]-t, menet közben át is méretezi a benne lévő array-t.
Kényelmessé és biztonságossá teszi a tömbkezelést.
A unique_ptr pedig általánosságban jó arra, hogy egy objektum felszabadításával ne kelljen foglalkozni.Ha ezeket nem használod és elfelejteted a delete-et, akkor keresheted, hogy miért növekszik a progid memóriahasználata (memóriaszivárgás).
[ Szerkesztve ]
-
Teasüti
nagyúr
válasz mgoogyi #4134 üzenetére
A new (new []) esetében egy pointer-t kapsz vissza
De hisz a tömb is egy pointer.Ha ezeket nem használod és elfelejteted a delete-et, akkor keresheted, hogy miért növekszik a progid memóriahasználata (memóriaszivárgás).
Mi van akkor, ha egy függvény minden lefutáskor létrehoz egy tömböt és elfelejtem törölni miután lefutott, majd újra meghívom a függvényt? Más memóriaterületen fogja megint létrehozni ugyanazt a tömböt?(#4133) dabadab
Áhhá!! Értem.
Ezt mintha olvastam is volna, hogy adott esetben egy szinttel feljebb szokták törölni, mondjuk az adott függvényen kívül.[ Szerkesztve ]
-
mgoogyi
senior tag
válasz Teasüti #4135 üzenetére
Igen, így van, a tömböt is pointerként kezeled. Gyakorlatilag a 0. elemére mutató pointer van a változóban értékként.
A kérdésedre a válasz igen, mindig más memóriaterületen kapsz egy új összefüggő memóriaterületet az új tömbödnek. A pointert írasd ki és látod, hogy mindig más értéket kap. Ez a logikai címe a kezdeti memóriacellának (a programod csak a memória egy számára logikailag elkülönített részét látja).
A régi tömb ugyanúgy meglesz az előző ciklusodból, csak a címe már nem lesz meg és anélkül nehéz felszabadítani.
Csináld ciklus belsejében simán, amit írtál. Ha jó sok kört fut a ciklusod, megzabálja a géped memóriáját.
Azért figyelj arra, hogy ne zabálja meg az összeset, kevés elemű int tömböt foglalj le 1000-szer ciklusban, kísérletnek elég.[ Szerkesztve ]
-
jattila48
aktív tag
válasz Teasüti #4135 üzenetére
"De hisz a tömb is egy pointer. "
Nem, nem az! C-ben valóban hasonlóan kezelheted a tömböt és a pointert, de ettől még a tömb nem pointer. Sok félreértés és hiba forrása ez, ugyanakkor nagyon kényelmes is tud lenni. A pointer egy változó, ami történetesen memória címet tartalmaz. Mint minden változónak, neki is van címe, és megváltoztathatod az értékét (balérték). Ezzel szemben a tömb egy konstans memória cím (ahol a tönb kezdődik). Ezt a konstanst a fordító/linker/betöltő számolja ki, amit te nem változtathatsz meg, és a címét sem képezheted (hiszen nem is létezik a memóriában).
int tomb[10];
tomb=new int[10]; //Hiba! tombnek nem lehet erteket adni, hiszen az konstans
int **ppi=&tomb; //Hiba! tombnek nem kepezheto a cime, mert az nem valtozo
int *pi=new int[10]; //OK
int **ppi=π //OK valtozonak kepezheto a cime
pi=new int[10]; //OK valtozo erteke megvaltoztathatoAmikor tömb elemre hivatkozol (kiindexeled), a fordító ehhez a konstans címhez adja hozzá az indexet, és erről a címről veszi elő a tömb elemet (intelnél egyetlen utasítás pl. : mov eax, DWORD PTR[ebx+0x1000]; indirekt indexelt címzési mód, ahol 0x1000-nél kezdődik a tömb, ebx-ben pedig az elérni kívánt tömbelem indexe található). Tehát itt a kódba a fordító beleírja a tömb konstans kezdőcímét.
Ha new-val foglalsz helyet, akkor a lefoglalt memória kezdőcímét egy változó kapja értékül, ez a változó a pointer. Ha ezen a memória területen tömb szintaxissal hivatkozol egy elemre, akkor a fordítónak (intel esetén) ehhez legalább két utasításra lesz szüksége. Az elsővel regiszterbe tölti a változó (pointer) címéről a változó értékét (ez maga a new-val foglalt memória kezdőcíme lesz). Ha pl. a pointered címe eax-ben van, akkor mov eax,DWORD PTR[eax] utasítás ezt megoldja. Majd az elem elérése mov eax,DWORD PTR[eax+esi] utasítással történik, ahol az esi tartalmazza azi indexet. Látható, hogy ez jóval lassabb művelet, mint az "igazi" tömb kiindexelése.[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
-
mgoogyi
senior tag
válasz jattila48 #4139 üzenetére
Ja értem, hogy mire gondolsz, én gyakorlatiasabban közelítem a kérdést.
int t[10] esetén a t a gyakorlatban úgy viselkedik, mint egy konstans pointer. Amikor a tömbről beszélek a kódban, akkor én a t-re gondolok, mint változóra, márpedig ez pontosan a 0. elem címe.
Az a konstans cím, amiről beszélsz, az maga a t változó tartalma. Annyit tud egy pointerhez képest, hogy a típusából kifolyólag tud arról, hogy hány elemű, azaz nem int * hanem int[10] típusú. De ettől még értékként a 0. elem címe van benne. És igen, valóban nem pointer, de mégis pontosan ugyanúgy viselkedik.Másrészt nem csak a stacken lehet a tömbünk, hanem a heapen is new-val foglalva, akkor meg direktbe egy int *-ba toljuk be a 0. elem címét és azzal a pointerrel is pont azt fogod csinálni, mint a stack-en foglalt t-vel.
Az assemblys részt elolvasom megint, amit írtál, abban nem vagyok otthon. Egyetemen meglehetősen félvállról vettem, így ennyi is maradt meg belőle. Egyébként aki most ismerkedik a C++-szal, annak lehet inkább riasztó, mint segítség.
-
jattila48
aktív tag
válasz mgoogyi #4140 üzenetére
Attól tartok, teljesen félreérted.
"...én a t-re gondolok, mint változóra"
Ahogy írtam, a t NEM változó, hanem konstans és ez a lényeg. Ha azt írod, hogyint i=j+3;
akkor az i és j változók, amik a memóriában futás időben keletkeznek, a 3 viszont konstans, ami sehol nem tárolódik el e memóriában, hanem a generált kódban jelenik meg mint konstans adat. Hasonlóan a tömb esetén is, sehol nem tárolódik a tömb (mint cím) értéke, hiszen csak egy konstans.
"Az a konstans cím, amiről beszélsz, az maga a t változó tartalma"
Nincs semmiféle t változó.
"Annyit tud egy pointerhez képest, hogy a típusából kifolyólag tud arról, hogy hány elemű"
Nem, nem tud róla hogy hány elemű, hiszen a konstansban ez nincs kódolva. C-ben egyébként sincs tömb index ellenőrzés (futás közben), és a fordító sem különböztet meg ez alapján típusokat (template-tel megoldható, ha a tömb méret template argumentum).
"nem pointer, de mégis pontosan ugyanúgy viselkedik"
Nem pontosan úgy viselkedik, ahogy előző hozzászólásomban írtam, nem adható neki érték, és nem képezhető a címe (szemben a pointerrel).
"Másrészt nem csak a stacken lehet a tömbünk, hanem a heapen is"
Nem, nem lehet a heapen tömb. Az nem tömb lesz, hanem dinamikusan foglalt memória, aminek a címe bekerül egy változóba (vagyis pointer), bár valóban kezelheted tömb szintaxissal, ha az elemeit akarod elérni. Tömböt deklarálni a stack-en lehet, vagy a globális adatterületen (amit a betöltő foglal le a memóriában).
"Egyébként aki most ismerkedik a C++-szal, annak lehet inkább riasztó, mint segítség."
A C++ nem egy egyszerű nyelv, és szerintem jó az elején tisztázni bizonyos dolgokat (pl. ezt), hogy később ne rögzüljön hibásan, mint ahogy az esetedben is.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #4141 üzenetére
"Nem, nem lehet a heapen tömb. Az nem tömb lesz, hanem dinamikusan foglalt memória"
Lehet én vagyok a retardált, de nekem a tömb = összefüggő memóriaterület egy adott típusra.
Szóval nekem van olyan, hogy statikusan allokált array és dinamikusan allokált array.https://msdn.microsoft.com/hu-hu/library/kewsb8ba.aspx?f=255&MSPPError=-2147217396
Az msdn meg le mer írni ilyet, hogy "When allocating an array using the new operator"?
"Ahogy írtam, a t NEM változó, hanem konstans és ez a lényeg."
int * a = new int[10];
int b[10];Pusztán ránézve a kódra én "a"-ra és "b"-re is változóként(előbbire pointer típusú változóként, utóbbira tömb típusúként) fogok hivatkozni. Utóbbi konstans és nincs mögötte valódi változó? Pont nem érdekel, nem látom a gyakorlati jelentőségét. Lehet ez rossz berögzültség, soha egyszer nem volt még hátrányom belőle a munkám során.
-
jattila48
aktív tag
válasz mgoogyi #4142 üzenetére
Nevezheted tömbnek a dinamikusan allokált memória területet, de az nem tömb abban az értelemben (konstans mérettel deklarált tömb), ahogy írtam. A különbséget nem írom le még egyszer.
"Pusztán ránézve a kódra én "a"-ra és "b"-re is változóként(előbbire pointer típusú változóként, utóbbira tömb típusúként) fogok hivatkozni."
b nem változó, hiszen nem változhat az értéke, mint ahogy egy változónál (a nevében is benne van) ez megtörténhet. Ennyi erővel a 3-at is nevezheted változónak, holott az sincs sehol a memóriában eltárolva. A tömb esetében kicsit azért kevésbé nyilvánvaló, hogy nem változó, hanem konstans, mert nevet adsz neki. A 3 leírva konstans literál, ezért nyilvánvalóbb hogy ő nem változó. Azonban írhatsz olyat, hogyconst int harom=3;
enum akarmi={nulla,egy,ketto};
ahol a névvel illetett számok szintén konstansok, nem lehet sem megváltoztatni az értéküket, sem a címüket képezni. A tömb ugyanilyen értelemben konstans. Ennek a látszat ellenére igenis van gyakorlati jelentősége, és illik is tudni róla. Csak erre szerettem volna felhívni a figyelmet„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #4143 üzenetére
Ok, főleg nevezéktanról beszélgetünk gyakorlatilag.
Én abból indulok ki, ahogy angolul hívni szoktunk dolgokat. Magyar szakirodalmat csak egyetemen olvastam utoljára kb.[https://msdn.microsoft.com/hu-hu/library/07x6b05d.aspx?f=255&MSPPError=-2147217396]
Pl:
"The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it."" you must declare your const variable as"
const int harom=3;
Szóval ez itt nekem egy konstants változó. Hülyén hangzik valóban.
-
jattila48
aktív tag
válasz mgoogyi #4142 üzenetére
"Pont nem érdekel, nem látom a gyakorlati jelentőségét"
Pl. az lehet a gyakorlati jelentősége, hogy innen már világos, hogy a C/C++ -ban miért nem lehet dinamikus méretű tömböt deklarálni (bár mint most megtudtam, újabb C szabvány szerint lehet):
int n=10;
int a[n]; //hiba. tomb meret csak konstans lehetEzt kezdők általában nem szokták érteni.
Ha az új C szabvány ezt mégis megengedi, akkor a tömb címe szükségképpen eltárolódik a memóriában (mintha változó lenne), de a fordító nem engedi meg a megváltoztatását és a címének képzését (gondolom így van, de nem ismerem a C-nek ezt a lehetőségét).
Másik gyakorlatban fontos vonatkozása a dolognak, hogy a dinamikusan allokált memóriát fel kell szabadítanod (ha nem akarsz memory leaket), a tömböt pedig nem kell (sőt nem szabad!) felszabadítani (hiszen nem a heapen lett lefoglalva). Tekintsük a következő kódrészletet:int tomb[10];
int *dinamik_tomb=new int[10];
int *pointer;
pointer=tomb;
delete[] pointer; //hiba! nem szabad felszabaditani a tomb-ot
pointer=dinamik_tomb;
delete[] pointer; //OK, fel kell szabaditani a dinamik_tombotAmint látod, a pointer felszabadításánál észnél kell lenni, tudni kell, hogy tömb, vagy dinamikusan allokált memória terület címét tartalmazza-e. Ebből bizony sok hiba adódik (jó párat láttam már), és megy a fejvakarás, hogy miért száll el a program, hiszen a "tomb valójában pointer". Hát nem!
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz mgoogyi #4144 üzenetére
Nem, nem csak nevezéktanról, hanem lényeges különbségről van szó. A
const int harom=3;
kódban a harom semmilyen módon nem változó, mert a lefordított kódban nem a memóriában elfoglalt címe alapján fognak rá hivatkozni, hanem pl. egy értékadó utasításban konkrétan befordítják a 3 konstans értéket:x=harom;
lefordítva valahogy így fog kinezni:lea eax,DWORD PTR[ebp-12] ;x cime az eax regiszterbe kerul
mov DWORD PTR[eax],3 ;x a 3 konstanst kapja ertekul. a 3 itt jelenik meg a kodbanharom nevu valtozo pedig sehol nincs.Amit angolul idéztél, szerintem kissé értelem zavaró, mert valóban olyan változóként (mintha memóriában el lenne tárolva) hivatkozik rá, aminek az értékét nem lehet megváltoztatni. Ez szerintem nem így van (bár talán lehet fordító függő), annál is inkább, hogy a const int-ek és enumok lehetnek template argumentumok, amiket a fordító egész biztos konstans int-ként fog értelmezni mikor a template-et példányosítja. Sőt a tömb konstans mérete is lehet const int, vagy enum. Mikor a fordító a stack-en (vagy globális adatterületen)" lefoglalja" a megfelelő méretű memóriát a tömb számára, ott konkréten az adott konstans számszerű értékét fogja használni, nem pedig holmi memória címből képzett indirekt hivatkozást.
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #4146 üzenetére
Ezzel nem mondtál semmi újat. A gyakorlati jelentőség = hogyan használod a kódban.
Évekig dolgoztam c++-ban, csak a saját gyakorlati nevezéktanomban változónak hívom a konstansokat is (legalábbis a const int-eket pl). Viszont a #define-olt cuccokat viszont konstansnak hívom.
A const int nekem egy olyan változó, amin nem tehetek meg tetszőleges műveletet.És szerintem a kódodtól függ, hogy minden tekintetben konstans lesz vagy sem.
Ugyanis a kódodhoz hozzácsapva azt, hogy&harom
simán megy, kiírathatod, és így már igazi változód lesz.A const-ot egy optimalizációs tippnek tekintem a fordító számára.
Ez nyilván péklapáttal tarkónbaszós kód, de példának jó.
[ Szerkesztve ]
-
jattila48
aktív tag
válasz mgoogyi #4148 üzenetére
Ahogy írtam, a const int kezelése esetleg lehet fordító és helyzet függő, pl. a példa programodban képezhető a címe (bár sok értelme nincs, mivel értéket nem adhatsz neki). De amiket példákat írtam (template argumentum, tömb méret), valószínűleg az értékét mint konstanst fogja használni, hiszen fordításkor még semmilyen memória címet nem tulajdoníthat neki. Értékadásnál esetleg lehet más a helyzet, hiszen az értékadás futás időben történik, és ott hivatkozhat a konstansra a memória címén keresztül (sok értelme ennek sem lenne, esetleg gyorsabb lehet az újra fordítás, ha megváltoztatod a forráskódban a konstans értékét. Ez csak tipp).
A #define egy más kérdés, az pusztán szövegfeldolgozás. Ott tényleg semmi különbség nem lehet ahhoz képest, mintha a konstans literált írtad volna minden helyen.
Kicsit elkanyarodtunk a témától. A const int-et és enum-ot csak a tömb mint konstans cím hasonlósága miatt hoztam fel. Eredetileg arra válaszoltam, hogy a tömb nem pointer, még ha sokszor hasonlóan is kezeljük. A különbség gyakorlatban is fontos vonatkozására is felhívtam a figyelmet, amit minden programozónak tudni kell. A technikai különbségek (mi hogy fordul, mennyire hatékony) valóban nem életbe vágók, de érdemes tudni róluk.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
jattila48
aktív tag
válasz jattila48 #4149 üzenetére
Elnézést, a const int valóban olyan "változó", aminek nem lehet értéket adni. A static const int-re gondoltam, erre már áll az amit eddig írtam. Template argumentumként és tömb méretként is static const int használható, const int nem. Amiket a tömb vs. pointer témában írtam, azt fenntartom.
[ Szerkesztve ]
„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Apple AirPods Pro (2. generáció) - csiszolt almaságok
- Gyúrósok ide!
- Futás, futópályák
- sziku69: Szólánc.
- Ukrajnai háború
- Luck Dragon: Asszociációs játék. :)
- sziku69: Fűzzük össze a szavakat :)
- Mobil flották
- Samsung Univerzum: Így ismerhető meg a Galaxy AI bármilyen telefonon
- Vicces képek
- További aktív témák...