当我从常量引用调用方法时,程序失败

Program fails when I call a method from constant reference

本文关键字:程序 失败 方法 调用 常量 引用      更新时间:2023-10-16

所以,我有一个令牌类:令牌.h

class Token {
    std::string name; // token name
    int frequency;//frequency
    Vector lines;//lines where the token is present
public:
    //explanations for the methods in the Token.cpp
    Token(std::string tokenname, int linenumber);
    virtual ~Token();
    const Vector getLines() const;
};
#endif /* TOKEN_H_ */

令牌 cpp

Token::Token(string tokenname, int linenumber) {
    // TODO Auto-generated constructor stub
    name = tokenname;
    frequency=1;
    lines.push_back(linenumber);
}
Token::~Token() {
    // TODO Auto-generated destructor stub
}
std::string Token::getName() const{
    return name;
}
int Token::getFrequency() const{
    return frequency;
}
const Vector Token::getLines() const{
    const Vector vec = lines;
    return lines;
}

程序失败,当我将其传递给列表类的插入方法

class List {
private:
    class Node {
    public:
        Token data;
        Node* next;
        Node(const Token &dataItem, Node* nextptr);
        ~Node();
    };
    Node* first;
    int length;
public:
    List();
    virtual ~List();
    void insert(const Token &t);
};

列表.cpp:

List::Node::Node(const Token &dataItem, Node* nextptr): data(dataItem), next(nextptr){
}
List::Node::~Node(){
cout<<"dead"<<endl;
}
List::List() {
    // TODO Auto-generated constructor stub
    length = 0;
    first = nullptr;
}
List::~List() {
    // TODO Auto-generated destructor stub
    Node* temp = first;
    Node* newtmp;
               while(temp->next != nullptr){
                   newtmp = temp->next;
                   delete temp;
                   temp = newtmp;
               }
}
const int List::size(){
    return length;
}
void List::insert (const Token &t){
        Vector dammit = t.getLines();
}

我发现了插入中的哪一行(Vector dammit = t.getLines(((,所以我就这样离开了。它给了我这个错误消息:

双重释放或损坏(快速顶部(:0x0000000000c34040***

如果你想

运行,这里有一些来自主文件的东西:

int main() {
//  cout<<"tokens are here"<<endl;
//
    Token hit("aca", 1);
    Token hit2("ui", 2);
    Token hit1("111", 3);
    List list;
    list.insert(hit);
    list.insert(hit2);
    list.insert(hit1);
}

向量类:

class Vector {
int* store;
int capacity;
int next_index;
public:
    Vector();
    Vector(int initial_size);
    Vector(const Vector &v);
    virtual ~Vector();
    void push_back(int item);
    int pop_back();
    const int size() const;
    void resize();
    void operator =(const Vector &v);
    int& operator[] (int k);
    const int& operator[] (int k) const;
    friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};
Vector::Vector() {
    // TODO Auto-generated constructor stub
    store = new int [1];
    capacity = 1;
    next_index = 0;
}
Vector::Vector(int initial_size){
    store = new int [initial_size];
    capacity = initial_size;
    next_index = 0;
}
Vector::Vector(const Vector &v){
    store = v.store;
    capacity = v.capacity;
    next_index = v.next_index;
}
Vector::~Vector() {
    // TODO Auto-generated destructor stub
    delete[] store;
}
void Vector::resize(){
    std::cout<<"in resize"<<std::endl;
std::cout<<capacity<<std::endl;
    int length = capacity;
    capacity+=100;
    int* tempArray;
    tempArray = new int[capacity];
    for (int i=0; i<length; i++){
        tempArray[i] = store[i];
    }
    if (length>1)
    delete[] store;
    std::cout<<"finish re4size"<<std::endl;
    store = tempArray;

}
void Vector::push_back(int item){
    if(next_index >= capacity)
        this->resize();
    store[next_index] =item;
    next_index++;
}
int Vector::pop_back(){
    next_index = next_index-1;
    int last = store[next_index];
    return last;
}
void Vector::operator =(const Vector &v){
    //delete[] store;
    store = v.store;
    capacity = v.capacity;
    next_index = v.next_index;
}
const int Vector::size() const{
    return next_index-1;
}
int& Vector::operator[] (int k){
    //assert((k<next_index)&(k>=0));
    return store[k];
}
const int& Vector::operator[] (int k) const{
    //assert((k<next_index)&(k>=0));
    return store[k];
}
ostream& operator<<(ostream& os, const Vector& v)
{
    for(int i=0; i<=v.size(); i++){
       os <<  v[i]<< ' ';
    }
    return os;
}

in

Vector::Vector(const Vector &v){
    store = v.store;
    capacity = v.capacity;
    next_index = v.next_index;
}

现在,您有两个指向同一int* store;的向量

void Vector::operator =(const Vector &v){
    //delete[] store;
    store = v.store;
    capacity = v.capacity;
    next_index = v.next_index;
}

你做同样的事情。

当您致电时

const Vector Token::getLines() const{
    const Vector vec = lines;
    return lines;
}

vec = lines使用复制构造函数。您现在有指向同一商店的 vec 和行。

您返回行的副本,这将再次触发复制构造函数。第三个对象现在指向存储。

堆栈展开时,本地定义的vec将被销毁。 ~Vector delete的商店。现在,您有两个对象指向同一个已解除分配的存储。

噗嗤! 一旦你尝试用这些向量中的任何一个做很多其他事情。看起来返回的 Vector 的破坏首先命中并导致析构函数重新删除存储。

您需要为新存储分配存储,然后在 = 运算符和复制构造函数中将源存储的内容复制到新存储中。

Vector::Vector(const Vector &v){
    capacity = v.capacity;
    store=new int[capacity];
    for (size_t index; index < capacity; index++)
    {
        store[index] = v.store[index];
    }
    next_index = v.next_index;
}

Vector & Vector::operator =(const Vector &v){
    delete[] store;
    capacity = v.capacity;
    store=new int[capacity];
    for (size_t index; index < capacity; index++)
    {
        store[index] = v.store[index];
    }
    next_index = v.next_index;
}

std::copy 可用于代替 C++11 中的 for 循环。也可以使用旧的memcpy,但这只是因为存储是一种原始数据类型。

在我编辑时,感谢 Jarod42,还有一个小调整:

const Vector & Token::getLines() const{ //note the return of a reference. This avoids 
                                        // making a copy of lines unless the caller really 
                                        // wants a copy.
    // const Vector vec = lines; don't need to do this. lines is const-ified by the
    // const on the return type of the function
    return lines;
}

此错误与调用具有常量引用的方法无关,而是函数 getLines() 。例如,如果您采用hit1并直接调用函数getLines(),它仍然会崩溃。问题在于Token如何具有堆栈分配的属性Vector,而堆栈分配属性又具有int *属性。这不一定是问题,但根据您实现这些类的方式,它可能会导致内存冲突。

如果你想继续使用你的getLine()并且不能使用<vector>库,你可以将Tokenlines属性更改为Vector *,并相应地更改所有其他语法。还要记住初始化你的指针lines内存,否则它会崩溃。

但是,如果没有必要,我宁愿使用尽可能少的动态分配内存。就像另一位用户所说,在while(temp->next != nullptr)之前,您应该有一个条件if(temp != nullptr )