访问违规尝试读取填充了对象的向量

时间:2015-06-04 17:06:33

标签: c++ vector clone copy-constructor

  

编辑:我做了一些更改,并根据此帖子更新了代码   Kyle和Dieter的评论,所以我修复了我的Clone()函数和   添加了一个赋值运算符来实现三个规则。虽然这个   肯定非常需要修复,同样的错误占优势。也许是我的   赋值运算符错了?

我正在使用我在网上找到的更大项目的jsonplus库。 我需要在向量中保存Class CJsonArray的对象。 CJsonArray没有Copy-Constructor,但有一个指针属性,所以我试着自己制作一个(第一次做了一个复制构造函数,我是c ++的新手)。

以下是CJsonArray的相关部分:

cjsonarray.h

    class CJsonArray : public CJsonValue
    {
    private:
      std::vector <CJsonValue*> members;
    public:
        LIB_PRE CJsonArray();
        LIB_PRE CJsonArray(const CJsonArray * value);
        LIB_PRE CJsonArray(const CJsonArray &); //the added copy constructor
        LIB_PRE CJsonArray& operator=(const CJsonArray&);
        LIB_PRE ~CJsonArray();

cjsonarray.cpp

 CJsonArray::CJsonArray(const CJsonArray& ori) : members(ori.members.size()) {
        for (std::size_t i = 0; i < ori.members.size()-1; ++i)
            members[i] =ori.members[i]->Clone();
    }
CJsonArray& CJsonArray::operator=(const CJsonArray& ori){
    for (std::size_t i = 0; i < ori.members.size() - 1; ++i){
        this->members[i] = ori.members[i]->Clone();
    }   
    return *this;
}

另外,我必须在CJsonValue中实现clone()函数,它是一个抽象类和从它派生的类。以下是相关的代码段:

cjsonvalue.h

enum CJsonValueType
{
  JV_STRING,
  JV_NUMBER,
  JV_OBJECT,
  JV_ARRAY,
  JV_NULL,
  JV_BOOL
};

class CJsonValue
{
private:
  CJsonValueType type;
public:
  LIB_PRE CJsonValue();
  LIB_PRE virtual ~CJsonValue();
  LIB_PRE CJsonValue(CJsonValueType type);
  LIB_PRE virtual CJsonValue * Clone(); //the added Clone-Function
  LIB_PRE virtual jstring ToString() const = 0;
  LIB_PRE CJsonValueType GetType() const;
  LIB_PRE virtual void Clear(){};
};

cjsonvalue.cpp

    CJsonValue * CJsonValue::Clone(){
    return NULL;
}

派生类的例子,cjsonvaluenumber.h

    class CJsonValueNumber : public CJsonValue
{
private:
  int value;
public:
  LIB_PRE CJsonValueNumber(int value);
  LIB_PRE CJsonValueNumber(const CJsonValueNumber * value);
  LIB_PRE CJsonValue * Clone();
  LIB_PRE jstring ToString() const;
  LIB_PRE void GetValue(int & number) const;
};

cjsonvaluenumber.cpp

CJsonValue * CJsonValueNumber::Clone(){
    return new CJsonValueNumber(*this);
}
产生错误的

main.cpp:

 CJsonArray array1;
 CJsonArray array2;
 CJsonArray array3;
 CJsonArray array4;
 CJsonArray array5;

 array1.AddMember("test1");
 array2.AddMember("test1");
 array3.AddMember("test1");
 array4.AddMember("test1");
 array5.AddMember("test1");

 arrays.push_back(array1);
 arrays.push_back(array2);
 arrays.push_back(array3);
 arrays.push_back(array4);
 arrays.push_back(array5);

 std::string str = arrays[0].ToString();

错误:

  

Message.exe中0x026574BD处的未处理异常:0xC0000005:Access   违规读取位置0x00000000。

debuginfo软: 已经在第一个push_back上第一个条目的成员已经腐败。 在我实现Copy-Constructor之前,程序已经在第二次或第三次回击时崩溃了,我想因为vectore必须重新定位他的条目并且找不到它们?我很伤心,第一次不得不处理这个问题。

所以我的问题是:我复制构造函数是否错误?或者我完全是错误的方式,它与它无关?

我查看了许多处理类似问题的Stackoverflow问题,并试图遵循那里的建议,但我想我在此过程中做错了。

如果我需要提供更多信息,请与我们联系。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

CJsonValue::Clone()方法需要是虚拟的。如果CJsonArray对象存储CJsonValue个对象的集合(而不是CJsonValueNumber或其他对象),则编译器无法知道CJsonValueNumber想要覆盖{{1}如果它不是虚拟的话。

这会导致始终调用Clone()而不是CJsonValue::Clone()。此时,您的数组中有NULL引用,这可能会导致您在CJsonValueNumber::Clone()0x00000000定义为NULL0)时发生访问冲突。

由于0x00000000无论如何都是一个抽象类(CJsonValue方法是虚空),我也会使CJsonValue::ToString()虚拟空。这将保证必须通过继承类来实现Clone方法。

总结一下,将CJsonValue::Clone()的声明更改为:

CJsonValue::Clone()