編輯:TLDR;我是物件切片的受害者,對此我一無所知。現在原始問題如下。
我試圖了解std::vector<MyClass>當 MyDerived 的實體被push_backed時如何存盤物件。此外,迭代器如何知道下一個記憶體塊的開始位置,以便增量 運算子知道如何到達那里。考慮以下代碼示例:
#include <iostream>
#include <vector>
using namespace std;
class BaseShape
{
public:
// BaseShape() { cout << "BaseShape() "; }
virtual void draw() const { cout << "BASE?\n"; }
};
class Circle : public BaseShape
{
public:
Circle() { cout << "Circle()"; }
virtual void draw() const override { cout << "Circle!\n"; }
void *somePointer, *ptr2;
};
class Triangle : public BaseShape
{
public:
Triangle() { cout << "Triangle()"; }
virtual void draw() const override { cout << "Triangle!\n"; }
void *somePtr, *ptr2, *ptr3, *ptr4, *ptr5;
};
int main()
{
cout << "vector<BaseShape *> ";
vector<BaseShape *> pShapes{new BaseShape(), new Circle(), new Triangle(), new Circle()};
cout << endl;
for (vector<BaseShape *>::iterator it = pShapes.begin(); it != pShapes.end(); it)
{
cout << *it << " ";
(*it)->draw();
}
// vector<BaseShape *> Circle()Triangle()Circle()
// 01162F08 BASE?
// 01162F18 Circle!
// 011661A0 Triangle!
// 01162F30 Circle!
cout << "\nvector<BaseShape> ";
vector<BaseShape> shapes{BaseShape(), Circle(), Triangle(), Circle()};
cout << endl;
for (vector<BaseShape>::iterator it = shapes.begin(); it != shapes.end(); it)
{
cout << &(*it) << " ";
(*it).draw();
}
// vector<BaseShape> Circle()Triangle()Circle()
// 01162FD0 BASE?
// 01162FD4 BASE?
// 01162FD8 BASE?
// 01162FDC BASE?
return 0;
}
在vector::<BaseShape*> pShapes中,我了解 pShapes 僅存盤指向實際形狀地址的指標。然后,很容易知道使用 it 將記憶體地址增加多少,因為所有指標都將具有相同的記憶體大小。控制臺輸出顯示了*it“三角形”在記憶體中的跳躍方式。
現在,我的疑問是何時vector<BaseShape> shapes使用。也許我的理解是錯誤的,但我相信這shapes會直接為 BaseShape 物件存盤記憶體(稍后會詳細介紹)。但如果這是正確的,那么當我將一個Circle或一個Triangle物件推入其中時,怎么可能將所有物件連續存盤在記憶體中?這聽起來不太可能,因為它們的記憶體大小不同,Circle而且Triangle它們的記憶體必須與 BaseShape 物件的記憶體連續(例如 [BaseShape mem][Circle mem])。更重要的是,如何 it確切知道需要多少記憶體才能跳轉到下一個物件?在控制臺輸出中,我可以看到 it僅將記憶體地址增加了 4,這使我得出結論,不知何故,只有 BaseShape 部分存盤在記憶體中。[Circle mem] 剛剛掉了嗎?因為我可以看到呼叫了 Circle 建構式(如 中所示// vector<BaseShape> Circle()Triangle()Circle())。
我可能希望代碼無法編譯或警告我將 Circle 或 Triangle 存盤在shapes其中會導致資訊丟失,但事實并非如此,并且代碼有點作業。'有點'是因為draw()早期系結到 BaseShape 而不是正確地后期系結到 Circle 或 Triangle 作為虛擬方法應該。這表明shapes正在存盤連續的 BaseShape 記憶體塊...
我不是想在這里解決問題,我只是好奇 C 是如何作業的,以及我對 std::vector、指標或迭代器的誤解在哪里。
uj5u.com熱心網友回復:
當BaseShape按值將 s 存盤在向量中時,您將體驗到所謂的物件切片。
基本上所有只有派生類包含的資訊都被遺忘了,實際上只存盤了基類的資訊。所有物件的行為都與BaseClass物件一樣,唯一的例外是潛在的類不變數由于切片而被破壞。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/429315.html
