为什么我在打印值时得到垃圾值?
Why am I getting garbage values when I print the value?
我正在尝试了解 PIMPL 习语和一般的 C++。
我有一个带有 PIMPL 样式界面的 class,它将一个 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
tempBar
在构造函数的末尾被弹出堆栈,因为它是一个局部变量,所以你遇到了未定义的行为。
也许您想在析构函数中使用 new
和 delete
。
您正在存储临时地址。相反,您需要 分配 它:
Foo::Foo()
{
myBar = new Bar;
myBar->value = 7;
}
然后你必须遵循三原则,提供析构函数和复制构造函数。
mybar
是指向 Foo
构造函数中局部变量的指针。当构造函数退出时,变量消失了,但myBar
仍然指向旧内存。
既然要实现PIMPL,那真的只有一个选择。您需要使用 new
动态分配 myBar
,并在 Foo
析构函数中使用 delete
释放它。您还必须向 Foo
添加复制构造函数和复制赋值运算符,以避免内存泄漏:
Test.cpp
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;
}
Test.h
class Foo
{
private:
struct Bar;
Bar* myBar;
public:
Foo();
Foo(const Foo &src);
~Foo();
void printValue();
Foo& operator=(const Foo &rhs);
};
如果您不实施 PIMPL,那么还有另一种选择。使 myBar
成为 Foo
class 的非指针成员:
Test.cpp
Foo::Foo()
{
myBar.value = 7;
}
void Foo::printValue()
{
std::cout << "Value = " << myBar.value << std::endl;
}
Test.h
class Foo
{
private:
struct Bar
{
int value;
};
Bar myBar;
public:
Foo();
void printValue();
};
使用现代 C++,您可以通过这种方式实现 pimpl:
#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() {}
我正在尝试了解 PIMPL 习语和一般的 C++。
我有一个带有 PIMPL 样式界面的 class,它将一个 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
tempBar
在构造函数的末尾被弹出堆栈,因为它是一个局部变量,所以你遇到了未定义的行为。
也许您想在析构函数中使用 new
和 delete
。
您正在存储临时地址。相反,您需要 分配 它:
Foo::Foo()
{
myBar = new Bar;
myBar->value = 7;
}
然后你必须遵循三原则,提供析构函数和复制构造函数。
mybar
是指向 Foo
构造函数中局部变量的指针。当构造函数退出时,变量消失了,但myBar
仍然指向旧内存。
既然要实现PIMPL,那真的只有一个选择。您需要使用 new
动态分配 myBar
,并在 Foo
析构函数中使用 delete
释放它。您还必须向 Foo
添加复制构造函数和复制赋值运算符,以避免内存泄漏:
Test.cpp
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;
}
Test.h
class Foo
{
private:
struct Bar;
Bar* myBar;
public:
Foo();
Foo(const Foo &src);
~Foo();
void printValue();
Foo& operator=(const Foo &rhs);
};
如果您不实施 PIMPL,那么还有另一种选择。使 myBar
成为 Foo
class 的非指针成员:
Test.cpp
Foo::Foo()
{
myBar.value = 7;
}
void Foo::printValue()
{
std::cout << "Value = " << myBar.value << std::endl;
}
Test.h
class Foo
{
private:
struct Bar
{
int value;
};
Bar myBar;
public:
Foo();
void printValue();
};
使用现代 C++,您可以通过这种方式实现 pimpl:
#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() {}