为什么我在打印值时会得到垃圾值?

时间:2016-04-13 00:35:04

标签: c++ pointers struct pimpl-idiom

我试图了解PIMPL习惯用法和c ++。

我有一个带有PIMPL样式接口的类,它将int值设置为7.但是,当我打印它时,我得到一个垃圾值,我不明白为什么。

代码

Test.cpp的

#include <iostream>
#include "Test.h"
struct Foo::Bar
{
    int value;
};

Foo::Foo()
{
    Bar tempBar;
    myBar = &tempBar;
    myBar->value = 7;
}
void Foo::printValue()
{
    std::cout << "Value = " << myBar->value << std::endl;
}
int main()
{
    Foo myFoo;
    myFoo.printValue();
    return 0;
}

Test.h

class Foo
{
    private:
        struct Bar;
        Bar* myBar;
    public:
        Foo();
        void printValue();
        //~Foo();
};

输出

值= 2147120498

4 个答案:

答案 0 :(得分:4)

boolean是指向mybar构造函数中的局部变量的指针。当构造函数退出时,变量消失了,但Foo仍指向旧内存。

由于您要实施PIMPL,因此实际上只有一个选择。您需要使用myBar动态分配myBar,并在new析构函数中将其与delete一起释放。您还必须向Foo添加复制构造函数和复制赋值运算符,以避免泄漏内存:

Test.cpp的

Foo

Test.h

Foo::Foo()
{
    myBar = new Bar;
    myBar->value = 7;
}

Foo::Foo(const Foo &src)
{
    myBar = new Bar;
    *myBar = *(src.myBar);
}

Foo::~Foo()
{
    delete myBar;
}

Foo& Foo::operator=(const Foo &rhs)
{
    *myBar = *(rhs.myBar);
    return *this;
}

如果您没有实施PIMPL,那么还有另一种选择。让class Foo { private: struct Bar; Bar* myBar; public: Foo(); Foo(const Foo &src); ~Foo(); void printValue(); Foo& operator=(const Foo &rhs); }; 成为myBar类的非指针成员:

Test.cpp的

Foo

Test.h

Foo::Foo()
{
    myBar.value = 7;
}

void Foo::printValue()
{
    std::cout << "Value = " << myBar.value << std::endl;
}

答案 1 :(得分:3)

使用现代C ++,你可以这样做:

#include <memory>

class Foo
{
    struct Bar;
    std::unique_ptr<Bar> myBar;
public:
    Foo();
    ~Foo();
    void printValue();
};    

unique_ptr是少数使用不完整类型的标准库容器之一。这种方法的一个优点是,如果你犯了一个错误,例如注释掉析构函数,或者试图复制Foo,那么编译器会为你捕获它。

.cpp文件中的主体可以是:

Foo::Foo(): myBar( new Bar ) { myBar->value = 7; }
Foo::~Foo() {}

答案 2 :(得分:2)

tempBar在构造函数的末尾从堆栈中弹出,因为它是一个局部变量,因此您将遇到未定义的行为。

也许你想在析构函数中使用newdelete

答案 3 :(得分:2)

您正在存储临时地址。相反,您需要分配它:

Foo::Foo()
{
    myBar = new Bar;
    myBar->value = 7;
}

然后你必须遵循三条规则,提供一个析构函数和复制构造函数。