基本上,我正在尝试实现类似于vector的自己的数据类型。我这么做只是为了好玩。问题是,当我尝试放置string类型的新元素时,我经常会遇到分段错误(试图创建一个名为person的结构,但它也有同样的问题(。我认为在这种情况下最重要的一段代码(table.h(:
template<typename type>
class table
{
private:
type* elements = new type[0];
unsigned int length_ = 0;
void resize(int change)
{
length_ = length_ + change;
type* elements_ = new type[length_];
std::memcpy(elements_, elements, length_ * sizeof(type));
delete[] elements;
elements = elements_;
}
public:
/* ... */
void put(type&& element)
{
resize(1);
elements[length_ - 1] = element;
}
}
然后(main.cpp(:
/* ... */
int main()
{
table<string> t;
t.append("Hello World"); // segfault
for(string s : t) {cout << s << endl;}
/* But this works:
table<char*> t;
t.append((char*)"Hello World");
for(string s : t) {cout << s << endl;} */
}
在此代码中
length_ = length_ + change;
type* elements_ = new type[length_];
std::memcpy(elements_, elements, length_ * sizeof(type));
您正在递增length_
,然后将elements
数组中的那么多元素复制到新数组中。但elements
中只有length_ - change
元素。因此,它试图从数组边界之外复制数据,这是未定义的行为。
另外,正如有人在评论中提到的,对于std::string
这样的类型,不能使用std::memcpy
。它只能用于琐碎的可复制类型。你可以这样做:
unsigned int newLength = length_ + change;
type* elements_ = new type[newLength];
std::copy(elements, elements + length_, elements_);
length_ = newLength;
或者最好只使用std::vector<type>
template<typename type>
class table
{
private:
std::vector<type> elements;
public:
/* ... */
void put(type&& element)
{
elements.emplace_back(std::move(element));
}
}