在我的C ++程序中,我有一个带有成员变量的类,它是指向另一个类的对象的指针的向量。它还有一个成员函数,它应该将输入对象的引用添加到指针向量中,然后在向量中打印所有对象的名称以确保它有效。我使用此函数添加Obj1
和Obj2
,并希望控制台输出Obj1
然后Obj1Obj2
,而是输出Obj1
然后Obj2Obj2
。有人能解释为什么会发生这种情况,更重要的是如何解决这个问题?
我正在使用Visual Studio 2015.这是该程序的代码。
using namespace std;
class MyClass1 {
public:
string name;
MyClass1(string a) {
name = a;
}
};
MyClass1 Obj1("Obj1");
MyClass1 Obj2("Obj2");
class MyClass2 {
public:
vector<MyClass1*> vop;
string name;
MyClass2(string a) {
name = a;
}
void addObjtoVec(MyClass1 mc) {
vop.push_back(&mc);
for (int i = 0; i < vop.size(); i++) {
cout << vop[i]->name;
}
cout << endl;
}
};
MyClass2 Obj3("Obj3");
int main() {
Obj3.addObjtoVec(Obj1);
Obj3.addObjtoVec(Obj2);
}
答案 0 :(得分:2)
您正在将局部变量(参数)的地址推送到向量中。一旦局部变量超出范围,指针(仍然存储在向量中)就不再有效了。访问它会产生不确定的行为。
答案 1 :(得分:1)
void addObjtoVec(MyClass1 mc)
按值mc
获取。这使mc
变量addObjtoVec
的局部变量副本被调用。
vop.push_back(&mc);
存储指向mc
的指针,而不是原始变量,并且作为局部变量,mc
将超出addObjtoVec
末尾的范围,留下向量已满指向Crom的指针知道什么。基本上addObjtoVec
是Undefined Behaviour生成器。你不知道会发生什么。
解决方案:
您不需要在vector
中存储指针,这是非常好的。
vector<MyClass1> vop;
以后
vop.push_back(mc);
将消除mc
超出范围的问题以及在MyClass1
中将指针混合到静态和动态分配vop
的任何潜在问题。
示例:
#include <vector>
#include <string>
#include <iostream>
class MyClass1
{
public:
std::string name;
MyClass1(std::string a)
{
name = a;
}
/* consider using the member initializer list instead of initializing
* in the constructor body. It gives the compiler more optimization avenues
*
MyClass1(std::string a): (name(a)
{
}
*/
};
class MyClass2
{
public:
std::vector<MyClass1> vop;
std::string name;
MyClass2(std::string a)
{
name = a;
}
void addObjtoVec(MyClass1 mc)
{
vop.push_back(mc);
for (int i = 0; i < vop.size(); i++)
{
std::cout << vop[i].name;
}
/* consider using C++11 enhanced for loop when you want to iterate an entire container
for (MyClass1 & elem: vop)
{
std::cout << elem.name;
}
*/
std::cout << std::endl;
}
};
int main()
{
MyClass2 Obj3("Obj3");
Obj3.addObjtoVec(MyClass1("Obj1"));
Obj3.addObjtoVec(MyClass1("Obj2"));
}
如果必须使用指针,请将addObjtoVec
的定义更改为
void addObjtoVec(MyClass1 & mc)
通过引用传递mc
。
您必须自行整理指针的所有权以及谁负责删除。
答案 2 :(得分:-1)
除了John上面的回答之外,问题还在于你按价值传递Obj1
和Obj2
。这意味着addObjtoVec
函数有一个变量的本地副本,一旦函数返回就会超出范围。解决此问题的一种方法是更改“addObjtoVec”以接收引用:
void addObjtoVec(MyClass& mc)
这意味着该函数引用了您的全局声明,而不是本地副本。