-2

我正在使用 SDL 制作一个游戏,该游戏使用 libconfig 从文件中读取一些设置。问题是我创建了一个ClipList包含 astd::vector<SDL_Rect>来存储设置的类,但是当尝试将SDL_Rect对象添加到向量时,由于某种原因 push_back 什么也没做,我最终得到一个空向量。

这是课程:

class ClipList
{
    public:
        ClipList();
        ClipList(int);
        virtual ~ClipList();
        void addClip(int,int,int,int);
        void getClip(int,SDL_Rect*);
        int getLength();
    protected:
    private:
    std::vector<SDL_Rect> clips;
};
ClipList::ClipList(int l)
{
    clips.reserve(l);
}

void ClipList::addClip(int x,int y,int w,int h){
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
    clips.push_back(rect);
}

void ClipList::getClip(int i,SDL_Rect* rect){
rect = &(clips.at(i));
}

int ClipList::getLength(){
    return clips.size();
}

这是我初始化 ClipList 对象的函数。这个函数是从 main 调用的。

void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips){
    const Setting& root = placlips->getRoot();
    int x,y,w,h;
    try{
        Setting& clipsett = root["clips"];
        int cliplen = clipsett.getLength();
        clips = new ClipList(cliplen);
        flipclips = new ClipList(cliplen);
        for(int i=0;i<cliplen;i++){
            const Setting& c = clipsett[i];
            if(!(c.lookupValue("x",x)&&c.lookupValue("y",y)&&c.lookupValue("w",w)&&c.lookupValue("h",h))){
                continue;
            }
            clips->addClip(x,y,w,h);
        }
    }catch(const SettingNotFoundException &nfex){
        cerr << "Setting not found at" << nfex.getPath() << endl;
    }
}

无论对象是否在或中ClipList初始化,都不起作用。向量的容量发生了变化,但没有对象被存储,所以如果我尝试对向量执行任何其他操作,即使检查向量是否为空,我最终也会出现段错误。mainset_clipsclips.push_back(rect)

4

2 回答 2

1

我猜,函数的签名

void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips);

是罪魁祸首。您正在为此函数分配内存,clipsflipclips由于指针是按值传递的,因此调用函数看不到分配的内存。

如果将函数签名更改为:

void set_clips(Config* placlips, ClipList*& clips, ClipList*& flipclips);

你的问题应该会消失。

于 2014-04-13T03:49:37.037 回答
1

clips.push_back(rect)工作正常。您的set_clips函数分配新的 ClipList 实例,但不会将这些指针传递回调用者。调用者可能试图使用垃圾指针作为初始化实例,这就是你得到段错误的原因。

您需要将创建的对象传回。您应该使用类似 std::shared_ptr<> 的东西来代替裸指针。

更新如何在不使用 std::shared_ptr<> 的情况下执行此操作:

您需要跟踪所有权并处理异常情况。就实际传递而言,我使用的规则(最初来自“大规模 C++ 软件设计”中的 Lakos)是作为返回值的参数(当您尝试使用它们时)是指针,而只读参数是值或常量引用。返回值是第一位的。

因此,您的set_clips函数应如下所示:

void set_clips(ClipList** clips, ClipList** flip_clips, Config const& placlips)

当您调用时,set_clips您将一个指针传递给将接收分配值的每个指针,并将一个常量引用传递给该函数未修改的 placlips 对象。

你会这样:

ClipList* clips = 0;
ClipList* flip_clips = 0;
set_clips(&clips, &flip_flips, placlips);
// ... then do whatever comes next.

但是将这些规则与 std::shared_ptr<> 或 boost::shared_ptr<> 结合起来会更好,并且是“现代 C++”风格。

于 2014-04-13T03:51:13.150 回答