7

我有这个例子来生成一个向量中的唯一对象:

#include <iostream>
#include <vector>
#include <algorithm>

int v=0;

struct A
{
    A() : refValue( v++)
    { std::cout<<"constructor refValue="<<refValue<<std::endl; }
    A( const A &r ) : refValue(r.refValue)
    { std::cout<<"copy constructor refValue="<<refValue<<std::endl; }
    A& operator=( const A &r )
    {
        refValue = r.refValue;
        std::cout<<"operator= refValue="<<refValue<<std::endl;
        return *this;
    }
    ~A() { std::cout<<"destructor refValue="<<refValue<<std::endl; }

    int refValue;
};

A GenerateUnique()
{
    A unique;
    return unique;
}
struct B
{
    B( const int n) : v()
    {
        std::generate_n( std::back_inserter( v ), n, &GenerateUnique );
    }
    std::vector< A > v;
};

int main()
{
    B b(3);
}

如果我将我的主要内容更改为:

struct B
{
    B( const int n) : v(n)
    {
    }
    std::vector< A > v;
};

然后将一个 A 类型的对象复制到所有向量元素中。

有没有办法创建一个包含所有唯一对象的向量(如第一个示例)?

为了更清楚:我有一个包含向量的类。此向量必须包含所有唯一对象(不是一个对象的副本)。我想在初始化列表中初始化它(而不是在构造函数的主体中)。

4

3 回答 3

3

它被复制是因为该构造函数的签名如下:

​explicit vector( size_type count,
             const T& value = T(),
             const Allocator& alloc = Allocator());

很明显,您只需将一个默认构造的对象传递给此构造函数,然后它就会复制它。

如果你想在初始化列表中进行初始化,显然你只能使用某些对象的构造函数。我想,你不会想创建一个包装类来初始化初始化列表中的向量,所以我们仅限于向量的构造函数。唯一看起来合理的是

template <class InputIterator>

vector( InputIterator first, InputIterator last,
        const Allocator& alloc = Allocator() );

因此,您可以创建一个迭代器来返回所需数量的默认构造对象。

我建议只是在构造函数体中构造。

于 2011-07-28T07:26:15.787 回答
3

您的第一次尝试是有效的。

在当前标准 C++03 中这一行

std::vector< A > as( n ); 

被明确定义为创建一个A对象并复制该n时间。

我相信在 C++0x 中,这被更改为创建n默认构造A的 s(一个小的差异)。然后你也许可以在As 构造函数中做一些事情来使每个实例都是唯一的。

现在你不能。

于 2011-07-28T07:30:29.023 回答
1

如前所述,您可以使用make_function_input_iteratorfrom boost 如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/iterator/function_input_iterator.hpp>

// A && GenerateUnique the same ...
struct B
{
    B( const int n) : v(boost::make_function_input_iterator(&GenerateUnique, 1), boost::make_function_input_iterator(&GenerateUnique, n))
    {
    }
    std::vector< A > v;
};

int main()
{
    B b(3);
}

但是请注意,当我测试代码时,我看到比您的第一个解决方案更多的复制构造/操作符=。除此之外,还创建了一个附加对象(参考值 3)(用于最后一个“停止”迭代器)。我不知道这种额外的行为是否可行,但如果你真的想要它,它会在你的初始化列表中初始化向量。

于 2011-07-28T09:22:16.090 回答