【问题标题】:Assign Index inside a class using std::vector使用 std::vector 在类中分配索引
【发布时间】:2018-09-18 00:23:11
【问题描述】:

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

#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&lt;Foo&gt; Instances (30, SomeVariablePassedByReference); 时,每个Instance 的每个成员变量Index 都得到相应的数字(0-30)。

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

【问题讨论】:

  • &amp;a -- 这不是参考。您正在使用 address-of 运算符,它返回一个指针。
  • 是的,我在做一个例子,我忘记了,但我已经编辑了。
  • 听起来你应该使用std::generate
  • Remy Lebeau 好吧,这是一个刚刚编辑的示例,问题不在于...
  • 所有错误都已编辑,抱歉我写得太快了

标签: c++ class vector operator-overloading stdvector


【解决方案1】:

您希望 Foo 的成员变量成为向量中的索引吗?只需调用每个成员的 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;

}

【讨论】:

  • @MatthewFisher 只是部分?
  • 我想我现在拥有它
【解决方案2】:

您在vector 的构造函数的第二个参数中传递的值按原样 传递给所创建的每个元素的复制构造函数。由于您正在创建Foo 对象的vector,第二个参数本身将是Foo 对象,因此您正在创建一个临时Foo,并将int 作为输入,然后将该临时参数传递给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


更新:感谢 cmets 中的 François Andrieux,我有了另一个想法,涉及 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

【讨论】:

  • @M.M 在我的第一个示例中,有 1 个 Foo 对象(隐式)在 main() 中构造,然后该 same object 将传递给 复制向量中每个对象的构造函数。如果我使用你所说的,向量中的每个对象都会以 same Index 值结束(在我的示例中为 0)。强制转换是必要的,因为 copy 构造函数要求 其输入参数由 const 引用传递,并且您通常不能修改 const 对象的成员。我正在更新源对象以在从它构造的每个副本之后增加其 Index
  • @M.M 是的,这不是复制构造函数的好用处。我在回答中也说了这么多。 在这个特定的用例中确实有效,但应该避免,是的。
猜你喜欢
  • 2013-02-17
  • 2014-01-18
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
相关资源
最近更新 更多