【问题标题】:Using dynamic memory allocation and overloading the assignment operator使用动态内存分配和重载赋值运算符
【发布时间】:2018-08-29 23:00:30
【问题描述】:

我正在学习 C++ 中的动态内存分配和重载运算符。 我正在尝试一个简单的程序来测试我的知识,但我无法找出我做错了什么。 代码如下:

#include <iostream>
#include <cstring>
using namespace std;
class myClass{
    private:
        char *ptr;
    public:
        myClass () {}
        myClass (char *str) 
        {
            ptr = new char[strlen(str)];
            strcpy(ptr, str);
        }
        myClass (const myClass &k) 
        {
            ptr= new char [strlen(k.ptr)+1];
            strcpy(ptr, k.ptr);
        }
        myClass& operator= (const myClass k)
        {
            delete [] ptr;
            ptr = new char [strlen(k.ptr)+1];
            strcpy(ptr, k.ptr);
            return *this;
        }
        ~myClass() {
            delete [] ptr;
        }
        void print() {
            cout<<*ptr;
        }
};

int main() {
    char s[6]="Hello";
    myClass p(s), m;
    m=p;
  m.print();
  return 0;
}

我正在尝试使用运算符 =,因此我可以将 ptr 的值从对象 p 分配给对象 m,但我没有得到任何输出。任何想法我做错了什么?

【问题讨论】:

  • myClass&amp; operator= (const myClass k) 应该是 myClass&amp; operator= (const myClass&amp; k)。不确定这是否能解决您的问题,但这是错误的。
  • myClass (const myClass &amp;k) 应该是 myClass (const myClass &amp;k):myClass(k.ptr){}myClass (char *str) 应该是 myClass (char const*str)。这两个都不是您的问题的原因。
  • @Yakk 修复了它,现在我只得到“H”作为输出。
  • 默认构造函数不初始化ptr。当默认构造的myClass 超出范围时,delete[] 将在未初始化的ptr 上被调用,如果幸运的话会导致崩溃。你还在吗?跟我说话。
  • myClass (char *str) 你没有分配足够的字节,导致未定义的行为。如果你解决了这个问题,那么你应该看到H作为输出(因为你决定输出ptr[0]而不是ptr

标签: c++ operator-overloading dynamic-memory-allocation


【解决方案1】:

在做

*ptr, *(ptr+1), ...

您只需访问 char 数组的一个元素。

我的更正:

void print() {
    cout << ptr
}

【讨论】:

    【解决方案2】:

    进行动态内存分配的最佳方法是让编译器为您完成,也许与std::stringstd::vector 等标准库容器配合使用。标准容器管理动态内存分配,无需费心费力。

    Read all about it.

    如果你真的需要自己动手,请阅读Rules of zero, three, and five.

    另外,学习copy-and-swap pattern. 使用operator= 的最佳方法是使用该模式。

    这是它的完成方式。当我忘记时,我将这段代码放在手边。如您所见,正确地制作容器并非易事。这就是我们使用 STL 容器的原因。

    namespace dj::example {
    
        template<class T>
        class my_vec
        {
        public:
    
            // constructors
            my_vec()
               : mSize(0)
               , mArray(nullptr)
            {}
    
            explicit 
            my_vec(std::size_t size) 
                : mSize(size)
                , mArray(new T[mSize]) // Can throw when size is huge
            {}
    
            // copy-constructor
            my_vec(const my_vec& other)
                : mSize(other.mSize)
                , mArray(new T[mSize]) // Can throw when size is huge
            {
                // For Visual C++
                // Put _SCL_SECURE_NO_WARNINGS in vc++ preprocessor 
                // to shut up VC++ about "deprecated" std::copy
                std::copy(other.mArray, other.mArray + mSize, mArray);
            }
    
            // destructor
            virtual ~my_vec()  // Make virtual in case my_vec is used as base class.
            {
                delete [] mArray;  
            }
    
            // Specialize external swap! Necessary for assignment operator below,
            // and for ADL (argument-dependant lookup).
            friend void swap(my_vec& first, my_vec& second) noexcept
            {
                // enable ADL (best practice)
                using std::swap; 
    
                // by swapping all the members of two objects,
                // they are effectively swapped
                swap(first.mSize, second.mSize); 
                swap(first.mArray, second.mArray);
            }
    
            // Assignment operator. Note that the argument "other" is passed by value.
            // This is the copy-and-swap pattern (best practice).
            // It assures that noexcept is true.
            my_vec& operator=(my_vec other) noexcept
            {
                swap(*this, other); // Uses specialized swap above. It must.
                return *this;
            } 
    
            // move constructor - construct and swap idiom (best practice)
            my_vec(my_vec&& other) noexcept
                : my_vec()
            {
                swap(*this, other);
            }
    
    
        // xxxxxxxxxxx
        // Everything below here is only to make my_vec a working example.
            // Member functions and typedefs below are for testing the example
            // ... not part of schema.
    
            using const_iterator = const T*;
            using iterator = T*;
            using size_type = std::size_t;
            using value_type = T;
            using type = my_vec<T>;
    
            iterator begin() { return mArray; }
            iterator end() { return mArray + mSize; }
            const_iterator begin() const { return mArray; }
            const_iterator end()  const { return mArray + mSize; }
            const_iterator cbegin() const { return mArray; }
            const_iterator cend()  const { return mArray + mSize; }
            T operator[](int i) const {
                return *(begin()+i);
            }
            T& operator[](int i) {
                return *(begin()+i);
            }
            std::size_t size()  const { return mSize; }
    
        private:
            std::size_t mSize;
            T* mArray;
        };
    
    } // namespace dj
    

    【讨论】:

      猜你喜欢
      • 2015-06-25
      • 2013-03-02
      • 2014-10-16
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      • 2013-04-18
      • 1970-01-01
      • 2023-04-07
      相关资源
      最近更新 更多