c ++向量丢失指针引用

时间:2012-12-11 19:49:51

标签: 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;
}

界面在

之下
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();
}

2 个答案:

答案 0 :(得分:5)

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

修复您的界面以避免深层复制,如下所示:

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

逐步了解代码的作用

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

答案 1 :(得分:1)

DClass::add函数中,BClass s是一个局部变量。

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

当您致电d->add(*b);时,您传递的值为BClass,这意味着您正在创建该副本,并且该副本的地址与原始地址不同。

函数返回后,

s将超出范围,指向它的指针将无效。因此存储该指针对您没有好处,因为取消引用它将是未定义的行为。