C ++在类的成员函数中追加指针向量,导致奇怪的行为

时间:2016-07-18 23:17:27

标签: c++ pointers vector

在我的C ++程序中,我有一个带有成员变量的类,它是指向另一个类的对象的指针的向量。它还有一个成员函数,它应该将输入对象的引用添加到指针向量中,然后在向量中打印所有对象的名称以确保它有效。我使用此函数添加Obj1Obj2,并希望控制台输出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);
}

3 个答案:

答案 0 :(得分:2)

您正在将局部变量(参数)的地址推送到向量中。一旦局部变量超出范围,指针(仍然存储在向量中)就不再有效了。访问它会产生不确定的行为。

答案 1 :(得分:1)

void addObjtoVec(MyClass1 mc)

按值mc获取。这使mc变量addObjtoVec的局部变量副本被调用。

vop.push_back(&mc);

存储指向mc的指针,而不是原始变量,并且作为局部变量,mc将超出addObjtoVec末尾的范围,留下向量已满指向Crom的指针知道什么。基本上addObjtoVecUndefined 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上面的回答之外,问题还在于你按价值传递Obj1Obj2。这意味着addObjtoVec函数有一个变量的本地副本,一旦函数返回就会超出范围。解决此问题的一种方法是更改​​“addObjtoVec”以接收引用:

void addObjtoVec(MyClass& mc)

这意味着该函数引用了您的全局声明,而不是本地副本。