【问题标题】:Why static vector of pointer to objects of a class is having garbage values?为什么指向类对象的指针的静态向量具有垃圾值?
【发布时间】:2021-06-05 15:06:46
【问题描述】:

我正在用 C++ 做一个关于 OOP 的项目,但遇到了一些错误(Segmentation Fault)。

sObjects 是一个静态向量,包含指向在Base 类中创建的每个对象的指针。

我还通过取消注释来检查地址: // cout<<(*it)<<endl; // cout<<this<<endl; .它们是一样的。

那么为什么我会收到垃圾值/分段错误? 我必须做某种类型的演员吗?

这是我的代码:

//main.cpp
#include <iostream>
#include "Base.h"
using namespace std;


int main()
{

    Base::UnitTest();

    vector<Base *>::iterator it;
    for (it = Base::sObjects.begin(); it < Base::sObjects.end(); ++it)
    {
        // cout<<(*it)<<endl;
        cout<<(*(*it))<<endl;
    }

    return 0;
}
//Base.h
#ifndef BASE_H
#define BASE_H

#include <iostream>
#include <vector>
using namespace std;

struct Node{
    int val;
};

class Base
{
private:
    Node node_;
public:
    Base(int a=0);
    ~Base();

    static vector<Base*> sObjects;
    friend ostream &operator<<(ostream &os, const Base &myObj);

    static void UnitTest();
};

#endif
//Base.cpp
#include "Base.h"
vector<Base*> Base::sObjects;

Base::Base(int a)
{
    this->node_.val=a;
    sObjects.push_back(this);
    // cout<<this<<endl;
}

Base::~Base()
{
}

ostream &operator<<(ostream &os, const Base &myObj)
{
    os<<myObj.node_.val;
    return os;
}

void Base::UnitTest()
{
    Base obj(23);
}

【问题讨论】:

  • 你没有在外部sObjects。这甚至是如何编译的?
  • 我正在基类的 UnitTest 中创建一个基类的示例对象,值为 23,但终端中打印的值是垃圾。
  • Base::UnitTest() 中创建的对象超出了范围,但是在它不再存在后您将其指针保留在您的向量中。这是一个悬空指针的实例。这是未定义的行为/任何事情都可能发生,包括它在某些时候似乎有效。幸运的是,您发现它不适用于您的情况。如果它即使坏了也能正常工作,情况会更糟。
  • @user2233706 它正在编译,没有任何错误。只是打印的值是垃圾
  • 打印的值是垃圾,因为向量在指向的对象被破坏后有一个悬空指针。

标签: c++ oop pointers casting


【解决方案1】:

Base::UnitTest() 中创建的对象超出范围,但是在它不再存在后,您可以在向量中使用sObjects.push_back(this); 保留指向它的指针。这是一个悬空指针的实例。这是未定义的行为。任何事情都可能发生,包括它在某些时候似乎有效。幸运的是,您发现它不适用于您的情况。如果它即使坏了也能正常工作,那就更糟了。

相关:What is a dangling pointer?

还有:What are all the common undefined behaviours that a C++ programmer should know about?

在同样的链接中,这是使用生命周期已结束的指针的情况。 使用指向生命周期已结束的对象的指针(例如,堆栈分配的对象或已删除的对象)

【讨论】:

    【解决方案2】:

    对象是在Base::UnitTest() 的范围内创建的。因此,您将指针保存在Base::UnitTest() 的函数堆栈调用中的内存Base::sObjects 中。为了避免这种行为,您可以在对象不再存在时从Base::sObjects 中删除指针。即,您可以在对象的销毁期间删除(在析构函数中)。

    【讨论】:

      猜你喜欢
      • 2016-01-26
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 2021-03-31
      • 2023-02-09
      • 2013-04-06
      相关资源
      最近更新 更多