我正在使用SDL制作游戏,该游戏使用libconfig从文件中读取一些设置。问题是我创建了一个名为ClipList
的类,其中包含std::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
或main
中set_clips
对象是否已初始化,clips.push_back(rect)
都无效。向量的容量发生了变化,但是没有对象被存储,所以如果我尝试用向量做任何其他事情,甚至检查向量是否为空,我最终会得到段错误。
答案 0 :(得分:1)
我猜,函数的签名
void set_clips(Config* placlips,ClipList* clips, ClipList* flipclips);
是罪魁祸首。您正在为此函数分配clips
和flipclips
的内存,但由于指针是按值传递的,因此调用函数不会看到已分配的内存。
如果您将功能签名更改为:
void set_clips(Config* placlips, ClipList*& clips, ClipList*& flipclips);
你的问题应该消失。
答案 1 :(得分:1)
clips.push_back(rect)
工作正常。您的set_clips
函数会分配新的ClipList实例,但不会将这些指针传递回调用者。调用者可能正在尝试使用垃圾指针作为初始化实例,这就是您遇到段错误的原因。
您需要将创建的对象传回。你应该使用像std :: shared_ptr&lt;&gt;这样的东西。这样做而不是裸指针。
在不使用std :: shared_ptr&lt;&gt;:
的情况下更新如何执行此操作您需要跟踪所有权并处理异常。就实际传递而言,我使用的规则(最初来自Lakos&#34;大规模C ++软件设计&#34;)是返回值的参数(当你试图使用它们时)是指针,并且读取-only参数是按值或const-reference。返回值是第一位的。
因此,您的set_clips
函数应如下所示:
void set_clips(ClipList** clips, ClipList** flip_clips, Config const& placlips)
当你调用set_clips
时,你传递一个指向每个将接收分配值的指针的指针,并将const-reference传递给未被该函数修改的placlips对象。
你会这样:
ClipList* clips = 0;
ClipList* flip_clips = 0;
set_clips(&clips, &flip_flips, placlips);
// ... then do whatever comes next.
但是将这些规则与std :: shared_ptr&lt;&gt;结合使用或者boost :: shared_ptr&lt;&gt;更好,现代的C ++&#34;风格。