Van erről valahol bugjelentés vagy cáfolat arra, hogy ennek így kell működnie?
Utána olvastam, már jó pár éve felhozták, de Visual Studio 2015 alatt ez még mindig hazavágja a programot: [link]
Valaki akinek hivatalos titulusa "Senior Google Searcher" belinkelhetné erről a dologról a Microsoft álláspontját, mert én hiába kerestem nem találtam.










# 1/1 Időpont ma 10:40
Bár jó észrevétel, de a probléma nem ott van. Valamiért az MSVC nem szereti emplace_back-nél az önmagára hivatkozást.
Egész pontosan akkor nem szereti amikor új területet kell foglalni az emplace_back során, hogy elférjen az új elem. Az apró probléma ebben, hogy érvénytelen lesz a régi referencia, ezért összeomlik a program vagy memóriaszemét lesz az új elem értéke.
Itt könnyedén megfigyelhető:
v.emplace_back(10);
int &i = v[0];
v.emplace_back(v[0]);
Ha nem kell új területet foglalni úgy megy:
v.reserve(2);
v.emplace_back(10);
v.emplace_back(v[0]);





# 3/3 Időpont ma 15:10
Valóban, csak én másik szemszögből próbálkoztam. Ez például lefut:
std::vector<std::string> v;
std::vector<std::string> v2;
v.emplace_back("I hate bugs!");
v2.emplace_back("I hate bugs!");
v2.emplace_back(v[0]);
Míg ha bármikor (reserve nélkül, tehát valóban új memóriaterületfoglalásnál) "önmagára" hivatkozok, akkor lesz bibi. G++ lefordítja gond nélkül.





Keresgéltem egy kicsit. A kód hibás (nem definiált viselkedést eredményezhet) és a javítás, hogy push_back-et kell hívni, mivel a második emplace_back hívásnál átméreteződhet a vektor és a v[0] a korábbi területre mutathat pillanatnyilag és más érték kerülhet be a vektor-ba.
Igen, de igazán implementálhatnák úgy az emplace_back -et, hogy ha új területet kell foglalni akkor:
1: Lefoglalja az új területet.
2: Létrehozza az új terület végén a kapott értéket.
3: Átmásolja az előző elemeket.
4: Felszabadítja az előző területet.
5: A régi terület mutatóját az új területre rakja.
Ezzel szemben a Visual Studionál ugyan úgy működik ha kell foglalni területet ha nem:
1: Lefoglalja az új területet.
2: Átmásolja az előző elemeket.
3: Felszabadítja az előző területet.
4: Létrehozza az új terület végén a kapott értéket.
5: A régi terület mutatóját az új területre rakja.





Bárhogy is van megvalósítva az átméretezés után az iterátorok és a referenciák érvénytelenek lehetnek. Benne van a szabványban, hogy csak átméretezés nélkül maradnak a vektor referenciái érvényesek. Pont a fenti kódban kellene lemásolni a v[0] elemét és a másolatot beadni. Eleve másolás történne, teljesen felesleges próbálkozás ezt elrejteni.
"Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,
all the iterators and references before the insertion point remain valid. If an exception is thrown other
than by the copy constructor, move constructor, assignment operator, or move assignment operator of
T or by any InputIterator operation there are no effects. If an exception is thrown while inserting a
single element at the end and T is CopyInsertable or is_nothrow_move_constructible<T>::value
is true, there are no effects. Otherwise, if an exception is thrown by the move constructor of a
non-CopyInsertable T, the effects are unspecified."
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!