【发布时间】:2014-07-26 23:25:28
【问题描述】:
背景
出于教学目的,我编写了一个模拟字符串操作的类Str。 Str 类本质上是一个字符数组。
我创建了一个函数makeList,它接收一个Str 对象,使用push_back 创建一个Str 对象列表并返回该列表。
我正在使用allocators,但我已加强内存管理,只为创建的字符分配足够的内存。
问题
编译、链接和运行时不会产生错误。
使用
cout << ret.back()在MakeList中查看列表对象内容正常。问题在于,在
main正文中查看时,列表中的对象的垃圾输入覆盖了前约 10 个字符。我还验证了我创建的
Str正在通过默认析构函数被销毁。
我已经包含了复制问题的最少代码量。
非类代码:
list<Str> makeList(const Str s)
{
list<Str> ret;
ret.push_back(s);
cout << ret.back() << endl;
return ret;
}
int main() {
Str greeting = "Hello world";
list<Str> result;
result = makeList(greeting);
result.pop_front();
cout << "The result is " << result.front() << endl;
return 0;
}
类代码:
class Str {
friend std::istream& operator>>(istream&, Str&);
public:
typedef char* iterator;
typedef const char* const_iterator;
typedef size_t size_type;
typedef char value_type;
Str() { create(); } // default constructor
Str(const_iterator cp, const_iterator cp2) {
create(cp, cp2);
}
Str(const_iterator cp) {
create(cp, cp + strlen(cp));
}
~Str() {uncreate(); }
char& operator[](size_type i) { return data[i]; }
const char& operator[](size_type i) const { return data[i]; }
Str& operator=(const Str& s) {
uncreate();
create(s.begin(), s.end());
};
Str substr(size_type i, size_type d) const {
const_iterator cStart, cTerm;
cStart = this->begin() + i;
cTerm = this->begin() + i + d;
Str sub(cStart, cTerm);
cout << "Pointer diff = " << sub.limit - sub.data << endl;
return sub;
}
size_type size() const { return avail - data; }
iterator begin() { return data; }
const_iterator begin() const { return data; }
iterator end() { return avail; }
const_iterator end() const { return avail; }
private:
iterator data;
iterator avail;
iterator limit;
allocator<char> alloc;
void create();
void create(const_iterator, const_iterator);
void uncreate();
};
void Str::create()
{
data = avail = limit = 0;
}
void Str::create(const_iterator i, const_iterator j)
{
data = alloc.allocate(j - i);
limit = avail = uninitialized_copy(i, j, data);
}
void Str::uncreate()
{
if (data) {
iterator it = avail;
while (it != data)
alloc.destroy(--it);
alloc.deallocate(data, limit - data);
}
data = limit = avail = 0;
cout << "UNCREATED" << endl;
}
ostream& operator<<(ostream& os, const Str& s) {
for (Str::size_type i = 0; i != s.size(); i++)
os << s[i];
return os;
}
【问题讨论】:
-
那么,复制/移动构造函数在哪里?它被称为例如
list<Str>::push_back编译器生成的不会做你想做的事(浅拷贝)。请遵循三规则(C++11 中的五规则)或零规则。 -
谢谢。这或许可以解释。我在线阅读了 push_back 操作的文档,但无法从用户定义的对象中找到它所需的内容。我不确定这是不是问题,因为 push_back 操作使用 makeList 函数中的 cout 创建了一个明显合适的列表。
-
我正在使用的教科书 AcceleratedC++,总体来说非常好,但在它的原始 Str 定义中也没有复制构造函数。
标签: c++ list memory-management allocator