簡體   English   中英

在類和構造函數中使用向量時出現分段錯誤

[英]Segmentation fault when using vectors in the class and constructor

我在做一個編程項目的清單,而這個項目是做一個15拼圖(slide拼圖)。 當我遇到一個小障礙時,我正在研究這個項目。

我的代碼編譯得很好,但是當我運行它時,在第 12 行出現分段錯誤: pos[0] = x;

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Tile{
private:
    vector<int> pos;
    int value;
public:
    Tile(int x, int y, int value_){
        pos[0] = x;
        pos[1] = y;
        value = value_;
    }
    ~Tile(){}
    int getPos(int a){return pos[a];}
    void setPos(int a, int b){pos[a] = b;}
};
int main(){
    Tile tile1(1, 2, 10);
    Tile* t1;
    t1 = &tile1;

    // returns position "x"
    cout << t1->getPos(0);
    return 0;
}

我的意思是,我可以完成整個項目而不必使用向量/數組來處理位置,但我仍然想知道,為了我將來的理解,為什么這不起作用。

根據我運行的調試,程序在初始化 pos[] 向量的值時遇到問題。

另一個問題:可能相關,我嘗試在實例化向量時設置向量的大小。

vector<int> pos(2);

但是后來我得到了調試錯誤:

error: expected identifier before numeric constant

不知道這里發生了什么。 我嘗試了很多不同的東西,但我似乎無法弄清楚為什么我的向量在類中不起作用。

我確信有一百種方法我可以把這個小作品做得更好,我很想知道你會如何修復它,但我也需要知道什么是錯的,特別是在我寫的內容的背景下並嘗試過。

謝謝。

我嘗試在實例化時設置向量的大小。

 vector<int> pos(2);

但是后來我得到了調試錯誤:

 error: expected identifier before numeric constant

那是編譯錯誤,而不是調試錯誤。

你不能像那樣初始化成員。 但是,您可以(並且應該)使用父構造函數初始化它們:

Tile(int x, int y, int value_)
    : pos(2)
{
    pos[0] = x;
    pos[1] = y;
    value = value_;
}

目前,您只是將向量留空,然后訪問(並寫入!)不存在的元素。

無論如何,你真的不想要一個向量:那是很多動態分配。 一個漂亮的數組怎么樣? 或者只是兩個int

正如其他答案中提到的,您的向量為空,您的代碼試圖分配不存在的元素。

解決方案是始終使用初始化程序而不是賦值。 重寫你的構造函數如下:

Tile(int x, int y, int value) :
    pos{x, y},
    value{value} {}

請注意,構造函數體現在是空的 所有初始化都發生在它應該發生的地方——在初始化列表中。

除此之外,您的類不需要顯式定義的析構函數; 默認的析構函數工作得很好。

這個類還有其他問題——例如,當用戶執行tile.setPos(3, 4)時會發生什么? 良好 API 設計的一個經驗法則是避免濫用 API。

下面是我將如何編寫您的Tile類:

struct Tile {
    int x;
    int y;
    int value;

    Tile(int x, int y, int value) : x{x}, y{y}, value{value} {}
};

你的情況下的 getter 和 setter 並沒有真正做任何有意義的工作。 有一個論點將所有數據成員隱藏在訪問者后面,以實現面向未來的訪問控制。 我不再相信這實際上很有用,但以防萬一,這里也有一個解決方案:

class Tile {
    int x_;
    int y_;
    int value_;

public:
    Tile(int x, int y, int value) : x_{x}, y_{y}, value_{value} {}

    int x() const { return x; }
    int& x() { return x; }

    int y() const { return y; }
    int& y() { return y; }

    int value() const { return value; }
};

這使得xy可讀和可寫(通過賦值: tx() = 42; ),並且value僅可讀。 其他 API 也是可能的,但要進行不同的權衡。 重要的是要保持一致。

您的構造函數沒有設置大小,因此當您嘗試訪問/修改其內容時,您可能會遇到異常。

Tile(int x, int y, int value_) : pos(2) {
    pos[0] = x;
    pos[1] = y;
    value = value_;
}

您可以使用構造函數的初始化列表來調用vector的構造函數,如上面的代碼所示。

給定的代碼中有幾個問題,我已經解決並在代碼中添加了注釋。

setPosgetPos可能會引起必須處理的分段錯誤。

添加了相同的檢查。

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Tile{
private:
    vector<int> pos;
    int value;
public:

    Tile(int x, int y, int value_){
        pos.push_back(x); // this is equivalent to pos[0] = x, in this case 
        pos.push_back(y); // this is equivalent to pos[0] = y, in this case
        value = value_;
    }

    ~Tile(){}

    int getPos(int a){
        if(a >= pos.size()){
            return -1; // if a is greater than size then pos[a] will raise the segmentation fault
        }
        return pos[a];
    }
    void setPos(int a, int b){
        if(a >= pos.size()){
            pos.resize(a+1); // to avoid segmentation fault, we are increasing the size if the given index is higher
            // resize initialise the value with 0 as default value.
        }
        pos[a] = b;
    }
};
int main(){
    Tile tile1(1, 2, 10);
    Tile* t1;
    t1 = &tile1;

    // returns position "x"
    cout << t1->getPos(0);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM