[英]C++ Shallow and deep copying - reflecting changes in the num_items of a vector
我目前正在大學攻讀C ++課程。 我了解使用向量進行淺層和深層復制的一般概念,但是我的教科書中有一個例子讓我感到困惑。
請假定它是一個實現較差的向量,未定義任何復制構造函數,因此它僅執行數據的淺表復制。
我了解第一部分的情況
在聲明中
vector<int> v2(v1);
將向量
v1
作為const引用參數傳遞給向量副本構造函數,因此無法更改v1
,然后將變量v2
初始化為向量v1
的副本。 每個數據字段都將被復制,以后對v2
所做的任何更改都不會影響v1
。 復制v1.the_data
的值時,v1.the_data
和v2.the_data
都將指向同一數組因為
v1.the_data
和v2.the_data
指向同一對象,所以該語句v1[2] = 10;
也更改
v2[2]
。 因此,將v2
視為v1
的淺表副本。
但是,我很難理解這一部分。 我不太確定為什么v2.num_items
也不會在淺表副本中更改。
該聲明
v1.push_back(20);
會將
20
插入v1[5]
並將v1.num_items
更改為6,但不會更改v2.num_items
。
我目前的想法是v1.the_data
和v2.the_data
指向內存中的同一位置,因此它們“共享”相同的向量,因此當在其末尾添加20時,兩個向量都應獲得一個附加的整數。
在理解為什么修改v1
后為什么v2
的項目數不會改變的過程中,我將不勝感激。
您的教科書是否在談論標准庫中的std::vector
? 如果是這樣,那是錯誤的。 vector<int> v2(v1);
從v1
復制構造 v2
。 這是一個深層副本,兩個容器不共享存儲,並且是完全分開的。
相反,如果這是一個不好實現的vector
類,並且容器共享存儲,則更改一個中的現有元素將反映在另一個中。 像push_back
這樣的操作更改了一個容器的num_items
但未更改另一個容器的num_items
,將導致它們在大小上存在分歧。
假設我們正在談論標准的std::vector
:
當您在此語句中復制向量時:
vector<int> v2(v1);
通過復制v1的每個元素來構建v2。 v1和v2不共享任何內存。
這部分 :
v1.the_data和v2.the_data都將指向同一數組
由於v1.the_data和v2.the_data指向同一對象,
是錯的。
您可以通過將每個向量的基礎數組地址與data()
成員函數進行比較來說服自己。
編輯:
假設您已經瘋狂到不使用std::vector
並使用在復制時會“共享”其后端數組的實現(我不會談論這種設計的問題:誰擁有數組?誰delete[]
它?)
您的老師提出的問題是,修改v1
(例如添加了元素)后, v2
對此一無所知,並且大小沒有變化。
數組的所有其他所有者都應觀察對一個矢量進行的任何push_back
(或類似操作),以正確反映數組的大小。
要么:
1)您實現某種觀察者模式,以使每個向量都知道任何修改(而且難度要比聽起來的難)
2)使用技巧將長度存儲在后端數組本身中。
通過矢量引用之一修改“共享”數組時,您將遇到類似的問題,使每個迭代器均無效...噩夢! 有充分的理由說明為什么STL容器全部設計為管理自己的內存,因此總是提供深層復制語義。
該語句似乎假定vector
的特定實現(與std::vector
不符)。 例如,假設我們有一個非常幼稚的實現:
template <typename T>
class Vector
{
T* myData;
int mySize;
int myCapacity;
public:
void push_back( T const& newValue )
{
if ( mySize == myCapacity ) {
// Extend the capacity...
}
myData[mySize] = newValue;
++ mySize;
}
T& operator[]( int index )
{
return myData[index];
}
};
如果沒有復制構造函數,則在復制向量時,所有三個變量都將具有相同的結果:兩個向量都將具有指向相同數據,相同大小和相同容量的指針。 但是這些是副本:使用[]
,修改myData
指向的內存,兩個向量都相同; 當你做push_back
上v1
,更新的大小 v1
,在其本地大小的副本。
當然,這種實現在許多方面都是幼稚的。 良好的std::vector
需要大量的考慮,這不僅是因為是否需要深層復制語義,還因為出於異常安全的考慮( T
的構造函數可能拋出),並且避免施加不必要的要求(在特別是默認構造函數)。
另外,如果我嘗試使用實施效果不佳的vector作為淺拷貝的示例,則不會將其稱為vector
,因為那樣會立即產生出std::vector
的圖像,這不應被實施不佳(並且不在我知道的庫實現中)。
在理解此問題中的陳述時,問題在於何時必須將vector視為std :: vector或作為理論實現。 std :: vector不允許淺表復制,其原因已在語句中給出:因此,不能尊重不變式。
現在,使用“ the_data”和“ num_items”成員的理論實現。 在這里,復制向量應提供深層副本,但僅復制“ the_data”將產生淺層副本,因為僅復制了指針。 這帶來了幾個問題:在一個向量中調整實際數據將導致另一個向量狀態不一致,並且無法再進行內存管理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.