Saya telah menemukan beberapa perilaku yang sangat aneh (pada dentang dan GCC) dalam situasi berikut. Saya punya vektor,, nodes
dengan satu elemen, turunan dari kelas Node
. Saya kemudian memanggil fungsi nodes[0]
yang menambahkan baru Node
ke vektor. Ketika Node baru ditambahkan, bidang objek panggilan direset! Namun, mereka tampaknya kembali normal lagi setelah fungsi selesai.
Saya percaya ini adalah contoh minimal yang dapat direproduksi:
#include <iostream>
#include <vector>
using namespace std;
struct Node;
vector<Node> nodes;
struct Node{
int X;
void set(){
X = 3;
cout << "Before, X = " << X << endl;
nodes.push_back(Node());
cout << "After, X = " << X << endl;
}
};
int main() {
nodes = vector<Node>();
nodes.push_back(Node());
nodes[0].set();
cout << "Finally, X = " << nodes[0].X << endl;
}
Output yang mana
Before, X = 3
After, X = 0
Finally, X = 3
Meskipun Anda akan mengharapkan X tetap tidak berubah oleh proses.
Hal lain yang saya coba:
- Jika saya menghapus baris yang menambahkan bagian
Node
dalamset()
, maka itu menghasilkan X = 3 setiap kali. - Jika saya membuat yang baru
Node
dan menyebutnya (Node p = nodes[0]
) maka hasilnya adalah 3, 3, 3 - Jika saya membuat referensi
Node
dan menyebutnya pada itu (Node &p = nodes[0]
) maka hasilnya adalah 3, 0, 0 (mungkin yang ini adalah karena referensi tersebut hilang ketika vektor diubah ukurannya?)
Apakah ini perilaku yang tidak terdefinisi untuk beberapa alasan? Mengapa?
reserve(2)
vektor sebelum memanggilset()
ini akan didefinisikan perilaku. Tapi menulis fungsi sepertiset
itu mengharuskan pengguna untukreserve
ukuran yang cukup sebelum memanggilnya untuk menghindari perilaku yang tidak jelas adalah desain yang buruk, jadi jangan lakukan itu.