【问题标题】:C++ Creating a copy constructor for stack classC ++为堆栈类创建复制构造函数
【发布时间】:2017-03-27 13:19:15
【问题描述】:

我定义了一个堆栈类,其中包含将值推送和弹出堆栈的方法。

在测试器文件中(如下所示),运行它后,发生了一个事件并且程序崩溃了。我知道这是由于函数 f 造成的,它会在两个指针指向内存中的同一位置时产生错误。如果我在调用函数时注释掉 f(s) 行,则 pop & push 函数可以正常工作并且输出正确。

为了解决这个错误,我被要求 ;为这个类创建一个拷贝构造函数来解决上面的问题。

我对此并不十分熟悉,因此如果能提供任何帮助,我们将不胜感激。谢谢

主测试文件

#include "Stack.h"
#include <iostream>
#include <string>
using namespace std;

void f(Stack &a) {
    Stack b = a;
}


int main() {

    Stack s(2); //declare a stack object s which can store 2 ints
    s.push(4); //add int 4 into stack s

    //s = [4]
    s.push(13); //add int 13 into stack s
    //s = [4,13]

    f(s); //calls the function f which takes in parameter Stack a , and sets Stack b = to it.
    //error here - as 2 pointers point to the same location in memory !
    cout << s.pop() << endl; //print out top element(most recently pushed) element.
    //so should output 13
    return 0;
}

头文件代码

#ifndef STACK_H
#define STACK_H

class Stack {
public:
    //constructor
    Stack(int size);

    //destructor
    ~Stack();

    //public members (data & functions)
    void push(int i);
    int pop();

private:
    //private members (data & functions)
    int stck_size;
    int* stck;
    int top;
};

#endif

Stack.cpp 代码

#include "Stack.h"
#include <iostream>
#include <string>
using namespace std;

Stack::Stack(int size){
    stck_size = size;
    stck = new int[stck_size];
    top = 0;
}
Stack::~Stack() {
    delete[] stck;
}
void Stack::push(int i) {
    if (top == stck_size) {
        cout << "Stack overflow." << endl;
        return;
    }
    stck[top++] = i;
}

int Stack::pop() {
    if (top == 0) {
        cout << "Stack underflow." << endl;
        return 0;
    }
    top--; //decrement top so it points to the last element istead of the empty space at the top.
    return stck[top];
}

【问题讨论】:

  • 错误可能在您的复制构造函数中(在 Stack.h 中)。
  • 包含上面的 stack.h 代码。我实际上还没有复制构造函数吗?这就是它要求我创造的东西。
  • 您需要向我们提供 Stack.h(至少)和 Stack.cpp(最好)的内容,以获得任何帮助。在不了解 Stack 实现的情况下,我们如何帮助您实现 copy ctor?
  • 您违反的是三法则。 What is The Rule of Three?点击链接一探究竟。它将为您节省大量的调试工作。
  • 不仅需要实现拷贝构造函数,还需要赋值运算符。

标签: c++ class stack push copy-constructor


【解决方案1】:

这里的复制构造函数非常快速和肮脏:

Stack::Stack(const Stack & src): 
    stck_size(src.stack_size),
    stck(new int[stck_size]),
    top(src.top) //Member Initializer List
{
    // copy source's stack into this one. Could also use std::copy.
    // avoid stuff like memcpy. It works here, but not with anything more 
    // complicated. memcpy is a habit it's just best not to get into
    for (int index = 0; index < top; index++)
    {
        stck[index] = src.stck[index];
    }
}

现在你有了一个复制构造函数,你仍然可能搞砸了,因为Rule of Three has not been satisfied. 你需要operator=。这很容易,因为复制结构和the copy and swap idiom makes it easy.

基本形式:

TYPE& TYPE::operator=(TYPE rhs) //the object to be copied is passed by value
                                // the copy constructor makes the copy for us.
{
  swap(rhs); // need to implement a swap method. You probably need one 
             //for sorting anyway, so no loss.
  return *this; // return reference to new object
}

【讨论】:

  • swap 在赋值运算符中不合适。右手边也不应该是可修改的。
  • @MarcD 我需要看到很多支持这两种说法。我将通过躲在Herb SutterScott Meyers 后面开始为我的观点辩护
  • 您没有按照herb sutter 的描述来实现这个成语。如果你正在实施一个动作很好,但你不是。第二,从什么时候赋值修改右手边???这既不是预期的,也不是期望的行为。如果您注意他给出的示例,他会使用对象的临时副本而不是对象本身进行交换。
  • @MarcD 当您将rhs 按值传递给operator= 时,它会生成一个临时副本。通过使用const 参考,Sutter 示例可能更加规范,但最后它做了完全相同的事情。它制作一个副本,然后交换。至于迈耶斯的链接,我很抱歉。我链接了错误的页面,不得不撤回那个例子。我暂时没有合适的替代品。至于返回引用,你需要它来获取A=B=C;链接。
  • 从语义上讲,您是不正确的,因为您通过交换内容使该类所做的每一个正常分配都无效。
【解决方案2】:

您的复制构造函数应该如下所示:

Stack::Stack(const Stack &r) {
    stck_size = r.stck_size;
    stck = new int[stck_size];
    top = r.top;
    memcpy(stck, r.stck, top*sizeof (int));
}

【讨论】:

  • 我需要什么 #include 才能使 memcpy 工作?给我错误提示找不到标识符
  • #include &lt;cstring&gt;
  • @LiamLaverty 不要使用 memcpy。它只会在以后给您带来这个确切的问题。 memcpy 真是太愚蠢了。它从 A 复制到 B,而不考虑是否应该这样做。这正是复制构造函数和赋值运算符的用途,memcpy 不知道如何使用它们。 Use std::copyfor 循环。
  • 至于这个答案,纯代码答案导致Cargo Cult programmers。对您所做的事情和原因进行一些解释,这可以作为补救措施。
  • @user4581301:好的,我会记住这一点。我几天前才开始在这里发帖,所以感谢您的课程。
猜你喜欢
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
相关资源
最近更新 更多