我喜欢创建具有给定大小和值的向量,例如:
std::vector<std::string> names(10);
然而,这几次导致了意想不到的结果。例如,在以下代码中,每个UniqueNumber
都具有相同的值:
#include <iostream>
#include <string>
#include <vector>
struct UniqueNumber
{
UniqueNumber() : mValue(sInstanceCount++)
{
}
inline unsigned int value() const
{
return mValue;
}
private:
static unsigned int sInstanceCount;
unsigned int mValue;
};
int UniqueNumber::sInstanceCount(0);
int main()
{
std::vector<UniqueNumber> numbers(10);
for (size_t i = 0; i < numbers.size(); ++i)
{
std::cout << numbers[i].value() << " ";
}
}
控制台输出:
0 0 0 0 0 0 0 0 0 0
在查看std :: vector的构造函数时确实有意义:
explicit vector(size_type __n,
const value_type& __value = value_type(),
const allocator_type& __a = allocator_type());
显然,矢量是用同一个物体的副本初始化的。
是否还有一种方法可以构建每个对象的默认值?
答案 0 :(得分:4)
Vector是复制构造元素以进行初始化。
试试:
#include <iostream>
#include <string>
#include <vector>
struct UniqueNumber
{
UniqueNumber(bool automatic = true)
: mValue(automatic?sInstanceCount++:Special)
{ }
UniqueNumber(UniqueNumber const& other)
: mValue(other.mValue==Special?sInstanceCount++:other.mValue)
{ }
unsigned int value() const
{
return mValue;
}
private:
static int sInstanceCount;
unsigned int mValue;
static unsigned int const Special = ~0U;
};
int UniqueNumber::sInstanceCount(0);
int main()
{
std::vector<UniqueNumber> numbers(10,UniqueNumber(false));
for (size_t i = 0; i < numbers.size(); ++i)
{
std::cout << numbers[i].value() << " ";
}
}
答案 1 :(得分:4)
有两种方法可以做到这一点。
漂亮的C ++ 0x方式是利用初始化列表:
std::vector<UniqueNumber> vec = { UniqueNumber(0), UniqueNumber(1) };
显然,这里的问题是你必须完整地指出它们。
在C ++ 03中,我只想使用循环:
std::vector<UniqueNumber> vec;
vec.reserve(10);
for (size_t i = 0; i != 10; ++i) { vec.push_back(UniqueNumber(i)); }
当然,这可以完美地嵌入到构建器函数中:
template <typename ValueType, typename Generator>
std::vector<ValueType> generateVector(size_t size, Generator generator)
{
std::vector<ValueType> vec;
vec.reserve(size);
for (size_t i = 0; i != size; ++i) { vec.push_back(generator()); }
return vec;
}
随着NRVO的推进,它大致相同,它允许您指定自由创建的值。
使用generate_n
中的STL <algorithm>
可以实现同样的效果,并且我将包含对lambda语法的感觉。
std::vector<ValueType> vec;
size_t count = 0;
std::generate_n(std::back_inserter(vec), 10, [&]() { return Foo(++count); });
@Eugen
在评论中提出的建议:)
注意:如果您希望拥有唯一元素,那么wrt会“惊喜”,或许vector
不是最合适的数据结构。如果你真的需要一个vector
,我会考虑包装成一个类,以确保元素是唯一的不变量。
答案 2 :(得分:4)
generate
或generate_n
是专为您想要做的事而设计的。这是一个完整的例子:
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
using namespace std;
class Foo
{
public:
Foo() : n_(++water_) {};
operator unsigned () const { return n_; }
private:
static unsigned water_;
unsigned n_;
};
Foo make_foo()
{
return Foo();
}
unsigned Foo::water_ = 0;
int main()
{
vector<Foo> v_foo;
generate_n(back_inserter(v_foo), 10, &make_foo);
copy(v_foo.begin(), v_foo.end(), ostream_iterator<unsigned>(cout, " "));
}
输出:1 2 3 4 5 6 7 8 9 10
答案 3 :(得分:3)
您需要添加复制构造函数:
UniqueNumber(const UniqueNumber& un) : mValue(sInstanceCount++)
{ }
std::vector
的填充构造函数未调用默认构造函数。相反,它调用默认存在的 copy 构造函数。那个构造函数当然不会增加你的内部静态计数器变量。
您还需要定义赋值运算符。
但是,使用具有std::vector
的内部静态计数器的对象将产生意外结果,因为该向量可以在内部复制构造/分配您认为合适的对象。因此,这可能会干扰您在此处所需的复制语义。