如何解决在构造函数中使用 std::initializer_list<std::string> 时出现分段错误
嗨,我想了解构造函数的工作原理,因此阅读了不同的示例。我有一个类构造函数,它需要一个 initializer_list,但它一直给 Segmentation fault
。我拥有的文件如下:
- strvec.h
class StrVec {
public:
StrVec(): elements(nullptr),first_free(nullptr),cap(nullptr) {
}
StrVec(const StrVec&);
StrVec(std::initializer_list<std::string> il);
StrVec &operator=(const StrVec&);
~StrVec();
void push_back(const std::string&);
void pop_back();
void reserve(std::size_t);
void resize(std::size_t,const std::string& = std::string());
bool empty() const {
return begin() == end();
}
std::size_t size() const {
return first_free - elements;
}
std::size_t capacity() const{
return cap - elements;
}
std::string *begin() const {
return elements;
}
std::string *end() const {
return first_free;
}
private:
static std::allocator<std::string> alloc;
void chk_n_alloc() {
if (size() == capacity()){
reallocate();
}
}
std::pair<std::string*,std::string*> alloc_n_copy(const std::string*,const std::string*);
void free();
void reallocate();
std::string *elements;
std::string *first_free;
std::string *cap;
};
- strvec.cpp
StrVec::StrVec(const StrVec &s){
auto newdata = alloc_n_copy(s.begin(),s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec::StrVec(std::initializer_list<std::string> il){
for(const auto &s:il){
push_back(s);
}
}
std::pair<std::string*,std::string*> StrVec::alloc_n_copy(const std::string *b,const std::string *e){
auto data = alloc.allocate(e - b);
return {data,uninitialized_copy(b,e,data)};
}
void StrVec::push_back(const std::string& s){
chk_n_alloc();
alloc.construct(first_free++,s);
}
- mainfile.cpp
int main() {
StrVec sv10 { "il1","il2","il3","il4","il5" };
return 0;
}
我的问题是如何解决这个问题,为什么我会收到这个 Segmentation fault
以及它意味着什么以便我可以在将来避免它?
PS:我知道错误是由于 StrVec(std::initializer_list<std::string> il);
构造函数造成的,因为如果我删除它并在 mainfile.cpp 中使用它,那么 Segmentation fault
就会消失。
解决方法
[这里只是猜测,因为您没有显示正确的 minimal reproducible example。]
你的类中有一组指针。
您的 StrVec(std::initializer_list<std::string> il)
构造函数不初始化这些指针,因此 push_back
很可能会使用这些未初始化的指针,您将拥有 未定义的行为和崩溃。
您可以通过委托默认构造函数轻松地进行默认初始化:
StrVec::StrVec(std::initializer_list<std::string> il)
: StrVec() // Delegte default initialization
{
for(const auto &s:il){
push_back(s);
}
}
话虽如此,std::initializer_list
将有一个大小,这意味着您可以预先分配所需元素的确切数量,然后复制它们,而不是在循环中调用 push_back
。>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。