【问题标题】:C++ Appending vector of pointers inside member function of a class causing odd behaviourC ++在类的成员函数内附加指针向量导致奇怪的行为
【发布时间】:2016-11-21 16:29:41
【问题描述】:

在我的 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);
}

【问题讨论】:

  • void addObjtoVec(MyClass1 *mc) {替换void addObjtoVec(MyClass1 mc) {,用vop.push_back(mc);替换vop.push_back(&amp;mc);,用Obj3.addObjtoVec(&amp;Obj1);替换Obj3.addObjtoVec(Obj1);,用Obj3.addObjtoVec(&amp;Obj2);替换Obj3.addObjtoVec(Obj2);
  • 成功了,非常感谢。

标签: c++ pointers vector


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    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 超出范围的问题以及由于在vop 中混合指向静态和动态分配的MyClass1s 的指针而导致的任何潜在问题。

    例子:

    #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

    您必须自行理清指针的所有权以及谁负责删除。

    【讨论】:

      【解决方案3】:

      除了上面 John 的回答之外,问题还源于您按值传递 Obj1Obj2 的事实。这意味着addObjtoVec 函数具有变量的本地副本,一旦函数返回,该变量将超出范围。解决此问题的一种方法是更改​​“addObjtoVec”以接收引用:

      void addObjtoVec(MyClass& mc)
      

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

      【讨论】:

      • 您仍然希望修复在向量中存储指针的问题。这是导致问题的可靠方法 - 它实际上只是在隐藏问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-12
      • 2013-03-31
      • 1970-01-01
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      相关资源
      最近更新 更多