正如其他人所指出的那样,问题在于您将临时变量的地址存储在指针变量中,并在临时变量超出范围(并已被删除)后取消引用该指针变量。
让我的回答更深入一点:
在 C++ 中,我们区分了值类和多态类。你会发现它们有不同的名字,你还会发现两者之间的区别并不像人们想象的那么明显,但大致是这样的:
值类实例的状态彼此不同。如果两个实例的状态相等,则实例的行为也将相等。
值类的示例是std::string
、所有 STL 容器std::complex<>
等。
您可以像使用int
s 一样使用它们:在堆栈上创建它们:
std::string s = "Hello, World"; // NOT std::string * s = new std::string;
按值聚合它们:
class Widget {
std::complex<double> m_value; // NOT std::complex<double> * m_value;
public:
// ...
};
您通常可以比较它们是否相等,复制它们,将它们存储在容器中:
std::vector<std::string> vec;
std::string s = "Hello, World";
assert( s == "Hello, World" );
vec.push_back( s );
并且,与您的问题最相关的是,您通过 (const-)reference (或按值,特别是如果它们非常小)传递它们,并且您也按值返回它们:
void func(const std::vector<double> & vec); // ok, just reading 'vec'
void func(std::vector<double> & vec); // ok, possibly writing to 'vec'
void func(std::vector<double> vec); // not so good, expensive in C++03; ok in C++11 in some situations
std::vector<double> func(); // ok, return value optimisation (look it up!) will make this fast
多态类的行为不同,而不是状态。多态类的两个实例可能具有相同的状态,但行为仍然完全不同。多态类的状态也可能不同,但重点在于它们的行为。这就是 OOP(面向对象编程)的全部内容。
从著名的 C++ 库“Qt”中借用示例类,aQLineEdit
和 aQPushButton
都是QWidget
s。它们可能具有相同的状态(大小、位置……),但是当您用鼠标单击每个状态时,它们之间会发生完全不同的情况。
在 C++ 中,要使用多态行为,您必须调用虚函数,并且必须通过指向公共基类的指针或引用来实现(QWidget
如上)。因此,多态类通常分配在堆上:
QLineEdit * le = new QLineEdit();
QPushButton * pb = new QPushButton();
QWidget * leAsWidget = le; // works
QWidget * pbAsWidget = pb; // works
并在(智能)指针变量中存储和传递:
class MyWidget : public QWidget {
QLineEdit * m_lineEdit;
QPointer<QPushButton> m_pushButton; // QPointer is a smart pointer
public:
// ...
};
对于您的程序,您必须决定是否需要deck
以及是否hand
是多态的。
如果是,请在堆上创建它们(使用new
),通过指针存储和传递它们,并且不要忘记在完成它们后再次删除它们(或查看智能指针)。
如果不是,则给它们关系运算符(bool operator==(const deck &lhs, const deck &rhs)
, ...),复制语义(deck(const deck&)
, deck &operator=(const deck&)
),在堆栈上创建它们并按值存储它们。通过 (const) 引用传递它们。您不需要删除它们,编译器会为您执行此操作。