class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef size_t size_type;
typedef T value_type;
explicit Vec(size_t n, const T & val = T());
private:
iterator data;
iterator avail;
iterator limit;
}
template <typename T>
Vec<T>::Vec<T>(size_t n, const T & val)
: data(new T[n]), avail(data + n), limit(data + n)
{
for (iterator p = data; p != avail; ++p)
*p = val;
}
我很难理解这里做了什么。
好的,所以我们有一个包含对象T的Vector的构造函数。我们传递size_type的大小,它包含一个数字和value_type T,其构造函数在参数字段中被调用。然后vector的构造函数创建一个对象数据。现在,我不明白对象数据的类型是什么,我不知道它为什么调用一个没有在任何地方定义的构造函数,我不太确定是什么& #39;在这里完成,因为我在定义构造函数时没有使用该语法,那么另一件事是我不知道什么是有用和限制的,以及为什么我们在运行时使用运算符size_type类型的对象和另一个不同类型的对象(是T的数据,可用和限制数组)。
答案 0 :(得分:2)
Vec
类会有其他未显示的成员:
T *data;
T *avail;
T *limit;
你似乎没有意识到这些变量存在;但你可以通过查找你找到的Vec
定义的其余部分找到它们来找到它们。
构造函数初始值设定项的语法(:
之后的内容)是name(value)
的列表。
这两者之间的区别:
Foo::Foo(string x): member_var(x) {}
Foo::Foo(string x) { member_var = x; }
是第一个,x
直接提供给data
的构造函数。在第二个中,首先使用其默认构造函数构造data
,然后调用其赋值运算符。这是一系列不同的事件;如果你有一个没有默认构造函数的类,那么第二个甚至不可能。
如果您不使用此构造函数语法,那么您应该开始使用它。
在您的示例中,data
被初始化为一些新分配的内存;指针avail
和limit
都设置为指向此分配块的末尾。
大概limit
表示已分配存储的结束,avail
表示向量中实际对象的结束。也许让这些size_t
包含对象计数而不是指针会更简单,但这两种方法是等价的。
为什么我们在size_type
类型的对象上使用运算符
我不确定你在这里想说什么。 n
的类型是size_t
(不是“size_type”),这是C ++的内置类型,它能够保存对象的最大大小。 typedef Vec::size_type
使得使用Vec
的人知道使用什么数据类型将索引保存到此向量中。
构造函数体内的代码循环遍历向量并将初始值复制到每个成员。