使用 std::vector 在 class 内分配索引

Assign Index inside a class using std::vector

我有一个 std::vector 30 个这样初始化的实例:

#include <vector>

class Foo {
public:

    int x;
    int Index;  // I want this to be initialized when std::vector start the 
                // Instances.

    Foo(int& _x) : x(_x) {} 

    int Function(){
        // Do something cool ...
    }

};

int main(){

    int a = 5;
    std::vector<Foo> Instances (30, a);
    return 0;

}

所以我想当我调用std::vector<Foo> Instances (30, SomeVariablePassedByReference);时每个实例的每个成员变量Index得到相应的数字(0-30)。

我怎样才能做到这一点?也许使用运算符重载?我不想使用 C-Stylish [ ] 运算符.

你想让Foo的一个成员变量作为vector中的索引?只需为每个成员调用 ctor 并将其推入向量。

#include <vector>

class Foo {
public:

    int a;
    int Index;  // I want this to be initialized when std::vector start the 
                // Instances.

    Foo(int _index, int& _x) : Index(_index), a(_x) {} 

    void func(){
        // Do something cool ...
    }

};

int main(){

    int a = 5;
    std::vector<Foo> Instances;
    Instances.reserve(30);
    for(size_t i=0;i<30;i++)
       Instances.emplace_back(i,a);
    return 0;

}

您在 vector 的构造函数的第二个参数中传递的值将 原样 传递给创建的每个元素的复制构造函数。由于您正在创建 Foo 个对象的 vector,因此第二个参数本身就是一个 Foo 对象,因此您正在创建一个带有 int 的临时 Foo作为输入,然后该临时值被传递给 vector.

中每个 Foo 实例的复制构造函数

因此,最接近您要查找的语法的是如下内容:

class Foo
{
public:
    ...
    int a;
    int Index;

    Foo(int _x) : a(_x), Index(-1) {} 
    Foo(const Foo &_f) : a(_f.a) { Index = ++(const_cast<Foo&>(_f).Index); } 
    ...
};

int main()
{
    int a = 5;

    // this (implicitly) creates a temp Foo object using the 'Foo(int)'
    // constructor, and then copy-constructs the Foo objects in the
    // vector passing that temp to the 'Foo(const Foo&)' constructor...
    std::vector<Foo> Instances (30, a);

    return 0;
}

Live Demo

但是,这是对 C++ 语言的明显不安全误用,所以不要使用它。

更安全的选择是在 vector 填充后简单地初始化索引,例如:

class Foo
{
public:
    ...
    int a;
    int Index;

    Foo(int _x) : a(_x), Index(-1) {} 
    ...
};

int main()
{
    int a = 5;
    std::vector<Foo> Instances (30, a);

    // yes, I know, you don't want to use the operator[], but it
    // is a safer option...
    for(size_t index = 0; index < Instances.size(); ++index)
        Instances[index].Index = index;

    // unless you use iterators instead...
    /*
    size_t index = 0;
    for (std::vector<Foo>::iterator iter = Instances.begin(); iter != Instances.end(); ++iter)
        iter->Index = index++;
    */
    /*
    size_t index = 0;
    for (auto &f : Instances)
        f.Index = index++;
    */

    return 0;
}

Live Demo


更新:感谢François Andrieux in comments, I had another idea involving std::generate_n()以您想要的方式为您创建索引。虽然它不是您正在寻找的语法:

#include <vector>
#include <algorithm>
#include <utility>

struct MyIndexGenerator
{
    int value;
    int index;

    MyIndexGenerator(int _value, int _first = 0) : value(_value), index(_first) {}

    std::pair<int, int> operator()()
    { 
        return std::make_pair(value, index++);
    }
};

class Foo
{
public:
    int x;
    int Index;

    Foo(const std::pair<int, int> &_x) : x(_x.first), Index(_x.second) {} 

    ...
};

int main()
{
    int a = 5;
    std::vector<Foo> Instances;
    Instances.reserve(30);
    std::generate_n(std::back_inserter(Instances), 30, MyIndexGenerator(a));
    return 0;
}

Live Demo