指针的矢量:为什么外部更改指针不会更改矢量元素
Vector of pointers: Why does changing the pointer externally not change the vector element?
请查看以下示例:
#include <iostream>
#include <string>
#include <vector>
class Base {
public:
virtual void price() const = 0;
};
class D1 : public Base {
public:
virtual void price() const {
std::cout << "Price of D1n";
}
};
class D2 : public Base {
public:
virtual void price() const {
std::cout << "Price of D2n";
}
};
int main()
{
std::vector<Base*> v;
Base* b = new D1();
v.push_back(b);
v[0]->price(); // "Price of D1n" - OK!
b = new D2();
v[0]->price(); // "Price of D1n"?! Why not "Price of D2n"
}
一个简单基类有两个派生类。在我的main()
中,我声明了一个包含指向基类的指针的向量,并用指向D1
对象的指针填充它。
当我将b
更改为指向D2的指针b = new D2();
时,为什么不相应地更改元素v[0]
?难道他们不应该指向同一件事吗?
我将尝试在较低层次上解释它。
首先,要理解指针本质上只是一个保存值的变量,而值恰好是内存中的一个地址
让我们简化一下,假设每个类型都有相同的大小,并且只有5个内存地址(在堆上(。(我也会忽略数组也会在堆上分配。(
我们现在执行
Base* b = new D1();
假设分配的内存位于地址3。CCD_ 6现在是一个简单地保持值3的变量。我们的(堆(内存如下所示:
0: ?
1: ?
2: ?
3: variable of type D1
4: ?
然后我们继续
v.push_back(b);
现在,数组v
包含一个值为3的条目。
b = new D2();
我们现在分配了一个新的内存部分,比如说在地址1:
0: ?
1: variable of type D2
2: ?
3: variable of type D1
4: ?
b
现在存储这个地址,也就是说,b的值是1。如果我们查看v
,我们没有更改它。它包含一个值为3的条目。
v[0]->price();
这给了我们一个值为3的指针,我们取消引用并打印它。给定上面的内存映射,存储在那里的是一个类型为D1的变量。
这为你澄清了事情吗?
我还对您的代码进行了一点扩展,以使用真实的地址来演示这一点:
http://www.cpp.sh/3s4b4
(如果您运行该代码,请注意,彼此紧接着分配的地址往往几乎相似,通常只相差一位数,因此请仔细查看。例如,我得到了0x1711260和0x1711220。(
如果你真的需要做你期望的事情,你可以在Base**
上存储一个向量,并在向量中存储b
的地址:
std::vector<Base**> v;
Base* b = new D1();
v.push_back(&b);
(*v[0])->price();
b = new D2();
(*v[0])->price();
实施日期http://www.cpp.sh/8c3i3.但如果你不是绝对需要的话,我不建议你这样做,因为它缺乏可读性,而且会造成不必要的混乱。(请注意,在本例中,第一个指针没有被删除,并且在更改b
后无法访问,因此我们会泄漏内存。(
当我将b更改为指向D2的指针时,b=new D2((;,为什么不相应地改变元素v[0]?难道他们不应该指向同一件事吗?
因为v.push_back(b);
在向量中存储指针b
的副本。因此,如果之后将b
更改为指向其他内容,则对v[0]
没有任何影响
你可以简化它,然后看到它是这样的:
int *ptr = new int;
int *ptr_copy = ptr;
*ptr = 2; //both *ptr and *ptr_copy have value: "2"
ptr = new int; //ptr now points to some other memory
*ptr = 5; //*ptr = 5, but *ptr_copy will still be "2"
现在,如果您真的希望即使在更改指针时也能反映更改,则需要另一个间接级别,即";指针到指针":
int main()
{
std::vector<Base**> v; //vector of Base**
Base* b = new D1();
v.push_back(&b);
(*v[0])->price(); // "Price of D1n" - OK!
b = new D2();
(*v[0])->price(); // "Price of D2n"
}
尝试此变体
vector<int> v;
int b = 123;
v.push_back(b);
cout << v[0]; // prints 123
b = 456;
cout << v[0]; // still prints 123
b
的变化不会改变v[0]
,这是很明显的,因为v[0]
的值是b
值的拷贝。但与您的代码相比,有什么不同?没有,完全相同的情况是v[0]
是b
的副本,更改b
不会更改v[0]
。您的案例涉及指针这一事实(在这方面(没有任何区别,因为指针没有什么特别之处。
将指针插入指针的std::vector
时,将该指针复制到容器中。之后
std::vector<Base*> v;
Base* b = new D1();
v.push_back(b);
您有两个指向D1
实例的指针:b
和vec[0]
。现在,如果你继续
b = new D2();
您只覆盖这两个中的一个,这显然是b
,但不是vec[0]
。因此,访问vec[0]
会首先为您提供对存储在那里的指针的引用。
- 调整大小后指向元素值的指针unordered_map有效?
- 当该数组的索引中没有元素时,指针指向什么?
- 如何在基类指针向量的元素上应用重载的多态函数
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 删除指针数组 (C++) 中的元素
- 从指向结构数组的指针中提取元素
- 指向数组基址的指针而不是指向第一个元素的指针有什么优点?
- 获取指向指针的指针元素 (c++)
- 经过最后一个数组元素末尾的指针是否应该等于超过整个数组末尾的指针?
- 存储指向动态数组元素的指针
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 取消引用C++中的指针元素
- 指针数组.获取指针元素的值
- C++访问带有迭代器的向量的指针元素
- C++:指针元素的向量在销毁时是否会自动释放每个指针所指向的动态内存?
- 打印整数指针元素时的结果不同
- 访问 c++ 的矢量指针元素
- 我必须手动删除QSet的每个(指针)元素吗?
- push_back在一行中指向Vector的非指针元素