代码之家  ›  专栏  ›  技术社区  ›  Oxymoron

为更好的编程实践征求意见

  •  2
  • Oxymoron  · 技术社区  · 15 年前

    当我学习C++时,我开始将一些常见的数据结构作为一种实践形式来实现。 我已经做了一些编程,它的工作,但现在我需要一些输入,我应该做什么,否则。比如删除某些东西或其他专业提示。我应该做些什么?为什么?

    template <class T>
    class Stack
    {
    private:
        int* values;
        int capacity;
        int itemsOnStack;
    
    public:
    
        /////////////////// 
        Stack()
        {
            Stack(32);
        }
    
        /////////////////// 
        Stack(const int sz)
        {
            values = new T[sz];
            capacity = sz;
            itemsOnStack = 0;
        }
    
        ~Stack()
        {
            values = 0;
                   // delete?
        }
    
        ////////////////////
        void Push(const T& item)
        {   
            *(values + itemsOnStack) = item;
    
            itemsOnStack++;
    
            if(itemsOnStack > capacity)
            {
                capacity *= 2;
    
                T* temp = new T[capacity];
                temp = values;
                values = new T[capacity]; 
                values = temp;          
            }
        }
    
        /////////////////// 
        T Pop()
        {
            if(itemsOnStack > 0)
            {
                int current = --itemsOnStack;
                return *(values + current);
            }
            return NULL; // ? good?
        }
    
        /////////////////// 
        T Peek()
        {
            if(itemsOnStack > 0)
            {
                int current = itemsOnStack - 1;
                return *(values + current);
            }
            return NULL; // find something better here or shouldnt?
        }
    
        /////////////////// 
        int Count()
        {
            return itemsOnStack;
        }
    
        /////////////////// 
        int Capacity()
        {
            return capacity;
        }
    
        /////////////////// 
        bool IsEmpty()
        {
            return itemsOnStack == 0;
        }
    };
    
    6 回复  |  直到 11 年前
        1
  •  7
  •   Stack Overflow is garbage    15 年前

    对您的代码进行了第一次修复:

    template <class T>
    class Stack
    {
    private:
        int* values;
        int capacity;
        int itemsOnStack;
    
    public:
    
        //Stack() : 
        //{
        //   Stack(32); // doesn't do what you expect. This would create an unnamed temporary stack object
        //}
    
        Stack(const int sz = 32) // C++ doesn't yet have delegating constructors. You can't call one ctor from another. But in this case, a simple default parameter can be used instead
       : values(new T[sz]), capacity(sz), itemsOnStack() {} // use the initializer list for initializing members
    
        ~Stack()
        {
            delete[] values; // you allocated it, so you delete it as well
        }
    
        ////////////////////
        void Push(const T& item)
        {   
            values[itemsOnStack] = item; // cleaner syntactically than your version
         //   *(values + itemsOnStack) = item;
    
            ++itemsOnStack; // prefer pre-increment by default.
    
            if(itemsOnStack > capacity) // you need to check this before writing the element. Move this to the top of the function
            {
                int newCapacity = capacity * 2;
    
                // what's this supposed to do? You're just copying pointers around, not the contents of the array
                T* temp = new T[newCapacity ];
                std::copy(values, values+capacity, temp); // copy the contents from the old array to the new one
                delete[] values; // delete the old array
                values = temp; // store a pointer to the new array
                capacity = newCapacity;
            }
        }
    
        /////////////////// 
        T Pop()
        {
            T result = Peek(); // you've already got a peek function. Why not use that?
            --itemsOnStack;
            return result;
        }
    
        /////////////////// 
        T Peek()
        {
            if(itemsOnStack > 0)
            {
                int current = itemsOnStack - 1;
                return values[current]; // again, array syntax is clearer than pointer arithmetics in this case.
            }
    //        return NULL; // Only pointers can be null. There is no universal "nil" value in C++. Throw an exception would be my suggestion
              throw StackEmptyException();
        }
    
        /////////////////// 
        int Count()
        {
            return itemsOnStack;
        }
    
        /////////////////// 
        int Capacity()
        {
            return capacity;
        }
    
        /////////////////// 
        bool IsEmpty()
        {
            return itemsOnStack == 0;
        }
    };
    

    有待解决的问题:

    复制构造函数和赋值运算符。现在,如果我试着这么做,它会崩溃得可怕:

    Stack<int> s;
    Stack<int> t = s; // no copy constructor defined, so it'll just copy the pointer. Then both stacks will share the same internal array, and both will try to delete it when they're destroyed.
    Stack<int> u;
    u = s; // no assignment operator, so much like above, it'll blow up
    

    常数正确性:
    我不能打电话吗 Peek() Count() const Stack<T> ?

    对象生存期:

    以及,呃,适当的测试:
    我没有以任何方式编译、运行、测试或调试过它。所以我很可能错过了一些错误,并引入了一些新的错误

        2
  •  4
  •   RC.    15 年前

    举几个例子和约翰所说的:

    1.)使用初始化列表
    2.)在适用的情况下使用const成员函数。
    3.)使用更符合标准的函数名(empty()而不是IsEmpty())
    4.)内存大量泄漏。销毁你的析构函数中的内存

        3
  •  3
  •   the_mandrill    15 年前

    你有很多内存泄漏,特别是如果你复制,分配或推到你的堆栈对象。甚至作为一个学习练习,我建议你不要做自己的内存管理(这是你需要在C++中学习的东西,但是一步一步地学习)。相反,使用std::vector或std::list,而不是原始的C样式的值数组。这意味着析构函数、复制构造函数、赋值运算符和Push()方法不会泄漏内存——它们在默认情况下也会做正确的事情(我称之为 最小惊奇原则 ). 我认为C++学习的一个重要部分就是知道如何使用STL。先了解这一点,然后再考虑指针和new[]以及delete[]。

    我建议您阅读一下复制构造函数、赋值运算符和析构函数,这样您就知道值实际上是如何被复制和删除的。尝试编写一个类:

    class Noisy {
      public:
        Noisy() { std::cout << "Constructor" << std::endl; }
        ~Noisy() { std::cout << "Destructor" << std::endl; }
        Noisy& operator=(const Noisy& other) {std::cout << "Assign" << std::endl; }
        Noisy(const Noisy& other) {std::cout << "Copy constructor" << std::endl; }
    };
    

    然后在上面做一些操作 Stack<Noisy> :

    Stack<Noisy> stack(10);
    stack.Push(Noisy());
    Stack<Noisy> otherStack(stack);
    Stack<Noisy> thirdStack;
    thirdStack=stack;
    

    看看你对它应该做什么的期望是否与你在控制台窗口中看到的相符。

        4
  •  1
  •   John Boker    15 年前

    你应该删除 values 在析构函数中,而不是将其设置为0;

    push 方法,则不能调整这样的数组大小。

    http://www.daniweb.com/forums/thread13709.html#

        5
  •  0
  •   ZeissS    15 年前

    Push() :在写入数组之前,应该检查数组的大小

        6
  •  0
  •   pm100    15 年前

     int *m_values;
     int m_capactity;
    

    你为什么这么做

     *(values + itemsOnStack) = item;
    

    我猜你是说

     values[itemsOnStack] = item;
    

    他们做完全相同的事情,但第一个更自然