[英]Copying values from one vector to another (from book)
考慮這段代碼。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int *> test;
vector <int *> v;
int *a = new int;
int *b = new int;
*a = 1;
*b = 2;
v.push_back (a);
v.push_back (b);
for (int i = 0; i < 2; ++i)
{
int n = *v[i];
test.push_back (&n);
}
cout << *test[0] << " " << *test[1] << endl;
delete a;
delete b;
return 0;
}
問題的陳述是:
“鑒於此代碼,請回答以下問題:
為什么“測試”向量僅包含2?
我們如何更改for循環以正確復制(僅for循環內的代碼)?”
我無法回答任何這些問題,因此將不勝感激。
提前致謝。
該代碼引入了懸空指針。 循環的主體如下所示:
{
int n = *v[i];
test.push_back (&n);
}
循環體結束時,局部變量n
失去作用域,因此指針&n
現在是懸空指針。 如果碰巧test
僅包含2,那就是從未定義行為中隨機產生的結果 。
如果要“正確”復制數據以進行test
,可以將for
循環體更改for
:
{
int* n = new int;
*n = *v[i];
test.push_back (n);
}
請“適量”加一粒鹽。
第一個問題是一個技巧性的問題:向量包含指向不再存在的變量的指針,並且取消引用可能會導致幾乎任何輸出。 我想在某些機器和編譯器上它會打印所有2
s。
我不明白該練習正在嘗試做什么(例如,為什么要使用指針向量),所以我無法真正幫助解決問題。
一種方法是按值存儲test
:
首先將測試向量更改為vector <int> test;
然后將push_back更改為test.push_back (n);
最后是print語句,以刪除現在不需要的*
運算符。
編輯評論:
首先,我懷疑這本書:它不應該顯示未定義的行為或指向單個內置類型的原始指針。 但是,您可以根據需要更改循環主體:
for (int i = 0; i < 2; ++i)
{
int* n = new int;
*n = *v[i];
test.push_back (&n);
}
請注意,除非您以后delete
這些指針,否則這兩種情況都會導致內存泄漏,從而消除了按值存儲的問題。
您將兩個相同的指針推到n
到test
數組中。 n
等於第一個數組的最后一個元素。 請注意,控制流退出循環后,所有指向n
指針都將變為無效。 因此,實際上您的test
數組包含無效的指針,而不是指向2s的指針。
您應該為每個整數創建一個副本:
int* n = new int(*v[i]);
test.push_back (n);
另請注意,此處內存泄漏。 使用new
創建的每個int都應在以后使用delete
銷毀。
1)我認為問題的前提是錯誤的。 循環添加了兩個要test
元素,每個元素都包含自動變量n
的地址,其范圍限於循環的主體。 不能保證在兩次循環中都將為n
分配相同的內存位置,但是我想大多數編譯器可能會在兩次循環中重用相同的位置。
此外, n
在輸出語句之外。 因此,未定義將test
的指針引用到那些內存位置。 同樣,很有可能它們仍將包含循環中分配的值。
因此,僅當在循環的第二遍中將相同的位置重用n
在執行輸出語句時該位置未被覆蓋時,輸出才為“ 2 2”。 這兩個場所均無法保證。
2)要獲得輸出“ 1 2”而不在循環外進行任何更改,可以將n
的定義更改為int& n = *v[i]
,盡管最終結果是給定代碼的單個字符更改有點奇怪
一個更簡單的解決方案是消除臨時n
並只需test.push_back(v[i])
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.