怎么只有一条线告诉我操作员=不可行?但其他人还好吗?

时间:2017-06-24 05:21:06

标签: c++ memory-management operator-overloading smart-pointers initializer-list

我现在已经调试了近6个小时,我即将放弃。 是的,它只是一个学校项目。但我已经提交了我的副本,现在我只是想知道它为什么不起作用。

在我的smartPointer类中,我想重载operator =。这对我来说似乎很好,应该很好。但不,我的初始化列表构造函数中的一行代码导致编译器错误。我用&#34来标记它;问题在这里!!"。我不认为它与其他构造函数中的相同行有任何不同。如果我发表评论,它将编译。但显然它会因内存未分配而导致运行时错误。有什么我忽略的吗?请给我一些提示。哦,我知道我的代码有潜在的删除问题,以至于同一地址被多次删除,但我想继续自己调试。我只是想知道为什么只有那条特定的行引起问题,因为该行存在于其他构造函数中,但都很好。非常感谢。

#include <iostream>
#include <cstdlib>
#include <cassert>
#include <initializer_list>


using namespace std;

//--------------------------------------------------------
//smart pointer class;

template <typename T>
class smartPointer{
private:
    T* pointee;  //raw pointer;

public:
    smartPointer(T* raw = 0):pointee(raw){}

    smartPointer(smartPointer<T>& rhs){
        pointee = rhs.pointee;
        rhs.pointee = 0;
    }   


    //destructor;
    ~smartPointer(){
        if(pointee !=0) delete [] pointee;
    }

    smartPointer<T>& operator=(smartPointer<T>& rhs){
        if(this == &rhs) return *this;
        delete pointee;

        pointee = rhs.pointee;
        rhs.pointee = 0;
        return *this;
    }


    T* operator->() const{
        return pointee;
    }

    T& operator*() const{
        return *pointee;
    }

    T& operator[](int i) const{
        return pointee[i];
    }


};

//smart pointer class;
//--------------------------------------------------------

template <typename T>
class SA{

private:
    int low, high;
    smartPointer<T> p;

public:
    //default constructor
    //allows for writing things like SA a;

    SA(){low=0; high=-1;p=NULL;}

    //2 parameter constructor lets us write
    //SA x(10,20);

    SA(int l, int h){
        if((h-l+1) <= 0){
            cout<<"constructor error in bounds definition"<<endl;       
            exit(1);
        }
        low=l;
        high=h;
        p=smartPointer<T>(new T[h-l+1]);
    }

//----------------------------------------------------------------------------
//new code added below!!!!!!!!!

    //initializer list constructor;

    SA(initializer_list<T> l){
        int size = l.size();
        low=0; high=size-1;
        p=smartPointer<T>(new T[size]);    //Problem here!!!
        initializer_list<int>::iterator itr;
        itr=l.begin();
        for (int i=0; i<size; i++){
            p[i]= *itr;
            itr++;
        }
    }


//----------------------------------------------------------------------------
//new code above!!!!!!!!!

    //single parameter constructor lets us
    //create a SA almost like a "standard" one by writing
    //SA x(10); and getting an array x index from 0 to 9

    SA(int i){low=0; high=i-1;
    p=smartPointer<T>(new T[i]);
    }

    //copy constructor for pass by value and
    //initialization

    SA(const SA& s){
        int size=s.high-s.low+1;
        p=smartPointer<T>(new T[size]);
        for(int i=0; i<size; i++){
            p[i]=s.p[i];
        }
        low=s.low;
        high=s.high;
    }

    //destructor

//  ~SA(){}

    int getHigh(){
        return high;
    }

    int getLow(){
        return low;
    }

    //overloaded[] lets us write
    //SA x(10,20); x[15]=100;

    T& operator[](int i){
        if(i<low || i>high){
            cout<<"index "<<i<<" out of range"<<endl;
            exit(1);
        }
        return p[i-low];
    }

    //overloaded assignment lets us assign
    //one SA to another

    SA& operator=(const SA& s){
        if(this==&s) return *this;
        delete[] p;
        int size=s.high-s.low+1;
        p=smartPointer<T>(new T[size]);
        for(int i=0; i<size; i++)
            p[i]=s.p[i];
        low=s.low;
        high=s.high;
        return *this;
    }

    //overloads << so we can directly print SAs

    friend ostream& operator<<(ostream& os, const SA<T>& s){
        int size=s.high-s.low+1;
        for(int i=0; i<size; i++)
            os<<s.p[i]<<" ";
        return os;
    }

};



int main(){
    SA<int> z{10,20,30};
    cout<<"printing result for SA z {10,20,30};"<<endl;

    cout<<z<<endl;
    cout<<"SA z(1,3){10,20,30}; would not work because" <<endl;
    cout<<"both (1,3) {10,20,30} are parameters where the latter"<<endl;
    cout<<"one is a initializer_list. In addition, {} are used for"<<endl;
    cout<<" initialization not assignment. But this would work:"<<endl;
    cout<<"SA<int> x({5,6,7});"<<endl;

    SA<int> x({5,6,7});
    cout<<x<<endl;

//  SA<int> v(1,3){1,2,3};
    return 0;
}

2 个答案:

答案 0 :(得分:0)

我认为代码的问题是operator =的定义。我给你的建议是阅读this:这里有你为什么要将你的赋值运算符声明为const或者使用move assignment更改定义的原因。无论如何,我找到了另一种轻松实现智能指针的方法:Implementing a simple smart pointer in C++。正如你在那里看到的那样,它使用了一个特定的类来计算对分配的对象的引用。

(为什么不使用nullptr而不是将0分配给原始指针?)

答案 1 :(得分:0)

我看到两个问题::

  1. psmartPointer<T>类型的对象。它是在堆栈上创建的。不要删除!!您正在重载的作业中将其删除
  2. SA的默认构造函数不正确。 使用p初始化smartPointer<T>(nullptr)。我建议使用构造函数的初始化列表。
  3. 除此之外,您的智能指针还不够智能: 请参阅https://www.codeproject.com/Articles/15351/Implementing-a-simple-smart-pointer-in-c

    快乐学习:)