C++ vector 丢失指针引用

标签 c++ pointers runtime runtime-error

我应该在两行中得到相同的.. 发生了什么我得到了两个不同的值..就像它针对不同的位置.. 我认为错误在 d->add(*b)

输出是

  thiago 14333804
  Ph¿├┌ 2816532

为了更好地描述它,我把代码放在下面

我有一个程序

int main(int argc, char **argv) {

    CClass* c = new CClass();

    BClass* b = c->getNext();

    printf("%s %d \n", b->getValue(), b->getValue());

    DClass* d = new DClass();
    d->add(*b);

    printf("%s %d \n", d->getNext(), d->getNext());

    cin.get();

    return 0;
}

接口(interface)如下

class BClass
{
private:
    char* value;
    bool stale;
public:
    BClass(char* value);
    ~BClass(void);
    char* getValue();
    bool isStale();
};


class CClass
{
private:
    vector<BClass*> list;
public:
    CClass(void);
    ~CClass(void);

    BClass* getNext();
};


class DClass
{
private:
    vector<BClass*> list;
    static bool isStale(BClass* b) { return b->isStale();};
public:
    DClass(void);
    ~DClass(void);
    void add(BClass s);
    char* getNext();
};

然后执行

//BClass

BClass::BClass(char* value)
{
    this->value = value;
    this->stale = false;
}

BClass::~BClass(void)
{
}

char* BClass::getValue()
{
    return value;
}

bool BClass::isStale()
{
    return stale;
}



//CClass

CClass::CClass(void)
{
    list.push_back(new BClass("thiago"));
    list.push_back(new BClass("bruno"));
    list.push_back(new BClass("carlos"));
}


CClass::~CClass(void)
{
}

BClass* CClass::getNext()
{
    return list.at(0);
}

//DClass

DClass::DClass(void)
{
}

DClass::~DClass(void)
{
}

void DClass::add( BClass s )
{
    list.push_back(&s);
}

char* DClass::getNext()
{
    BClass* b = list.at(0);

    return b->getValue();
}

最佳答案

当您将 B 类的实例传递给 D::add() 函数时,您创建了对象的深层拷贝,并且该拷贝就是放在堆栈上的内容。稍后您使用 该拷贝的地址 将其推送到列表中。函数完成后,此自动变量超出范围,因此您用来放入列表的指针不再有效。

要修复更改您的界面以避免深度复制,如下所示:

void DClass::add( BClass * s )
{
    list.push_back(s);
}

逐步说明您的代码在做什么

  1. BClass* b = c->getNext();//从列表中获取第一个元素的地址(在构造函数中创建)并将其分配给 b
  2. d->add(*b);//*b 将解引用 b 指向的对象并将其放入堆栈以准备调用添加()
  3. void DClass::add( BClass s ){//解引用对象的深层拷贝被放入此函数的栈帧中
  4. list.push_back(&s);//原始对象的临时拷贝的地址用于添加到您的列表
  5. }//这就是有趣的地方 - 一旦函数完成,它将展开堆栈备份并且之前由该临时拷贝占用的内存将被重新用于其他目的。在您的情况下-它将用于将参数传递给函数 d->getNext() (总是有一个隐藏的 this 参数传递给非静态成员函数),然后再传递给printf() 函数。请记住 - 您之前指向该临时拷贝的指针仍指向堆栈,但它现在被不同的数据占用,导致您看到损坏

一般经验法则 - 永远不要使用指向临时对象的指针 ;-)

关于C++ vector 丢失指针引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13827426/

相关文章:

c++ - 小组项目剧院座位切换说明

c++ - 如果在 linux Ubuntu :)10. 10 中包含 boost/thread,则不会编译

c++ - 具有多个对象回调的游戏循环 - 第二个对象没有任何反应

c# - 如何使用 ref struct 参数和未知返回类型调用内部方法

c++ - struct 和 time_t 的计算错误

c++ - 使用 extern const 的函数初始化 const

c - 如何将二维数组静态初始化为指向指针的指针?

c++ - 为什么我们不能泛化指针声明?

java - 如何从 Java 代码中处理外部软件的 GUI

java - Java运行时如何获取变量声明的类型?