如何调整具有唯一对象的std :: vector的大小

3

我有一个对象向量。每个对象都有指向不可复制对象(boost::signal)的 boost::shared_ptr。该对象的默认构造函数创建 boost::signal 对象。

struct FuncRef
{
    typedef boost::signal0<void, > Func;
    boost::shared_ptr <Func> function;
    FuncRef():
        function(new Func)
    {
    }
};

为了使我的向量包含X个单独的对象,我做了以下操作: -
vec.resize(X);

这个并没有达到我的预期,因为它使用默认构造函数创建一个对象,然后使用复制构造函数来创建副本。最终我会得到X个对象,但是它们都指向同一个boost::signal0对象。
是否有更简单的方法来正确构建我的向量,而不只是在for循环中使用push_back

你可以让你的类继承 boost::noncopyable,以便在编译时检测此类错误。 - Björn Pollex
@Bjorn - 这个类必须是可复制的,因为它在一个向量中。这就是为什么我不得不使用 shared_ptr 的原因。问题是它在我没有预期的情况下使用了复制... - Roddy
正确的,我在想什么呢? - Björn Pollex
2
如果你使用的是C++0x,你可能想这样写:while (vec.size() < X) vec.emplace_back();。 这表明你不想进行任何复制,但可惜的是没有 emplace_several_times 。更好的方法是,它应该允许你使用 unique_ptr 而不是 shared_ptr ,这样你的元素是可移动但不可复制的。这使你能够实际禁止你不想要的复制。但是,在C++0x下,boost::signal本身是否可移动我不知道。 - Steve Jessop
3个回答

3
我能想到的唯一方法是使用reserve使向量分配所需的内存(如@Jonathan所回答的)。然后,您可以使用generate_nstd::back_inserter添加元素:
FuncRef makeFuncRef() {
    return FuncRef();
}

vec.reserve(vec.size() + n);
std::generate(std::back_inserter(vec), n, makeFuncRef);

这种方法不需要使用reserve,但如果n很大,使用它可能会更快。

1
我能想到的最简单的方法是事先保留内存,这样 vector 只需要进行一次分配。
vec.reserve(X);

然后循环并使用push_back()。这对您的需求不足吗?


是的,那个方法可以用,但我在想是否有一个简单的一行代码可以实现... - Roddy
Björn的std::generate()想法很正确。不清楚你想将向量元素初始化为什么。它们必须保持某个值(或未定义)。 - Jonathan Grynspan
使用代码中显示的FuncRef构造函数将其初始化为默认构造对象。Bjorn的代码将按原样工作,但是对于循环来说,我认为可读性更好。期待lambda的到来... - Roddy
Lambda表达式也很好用,但你没有指明你可以使用C++0x的特性。 :) - Jonathan Grynspan

0

您无法使用实际复制语义实现复制构造函数/复制赋值运算符吗?除非您在向量填充方面有严重的性能问题,否则这似乎是最明显的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接