在创建对象向量

时间:2018-06-13 10:50:53

标签: c++ vector

我正在尝试创建一个对象向量,并希望为向量中的每个对象唯一地调用非默认构造函数。我在下面有一个简化的例子。

在我的例子中,我有一个带有两个构造函数的对象,默认(无args)和非默认(1 arg)。当我使用默认构造函数(v1)初始化大小为10的向量时,构造函数被调用10次(随机数可以看到)。但是,当我尝试使用对象非默认构造函数(v2)初始化向量时,对象构造函数被调用一次,并且此对象被复制到向量中的其余元素(x不再是许多不同的随机数)。 / p>

是否可以初始化N个对象的向量,以便为每个对象调用每个对象的非默认构造函数?

示例代码:

#include <vector>
#include <iostream>
#include <cstdlib>

struct Obj {
    int x;

    Obj() {
        x = rand() % 5;
    }

    Obj(int max_x) {
        x = rand() % max_x;
    }
};

int main() {
    std::vector<Obj> v1(10);     // Default constructor
    std::vector<Obj> v2(10, 5);  // Non-Default Constructor

    for(int i=0; i<10; ++i) {
        std::cout << v1[i].x << ", " << v2[i].x << std::endl;
    }
}

输出:

3, 2
1, 2
2, 2
0, 2
3, 2
0, 2
1, 2
2, 2
4, 2
1, 2

解决方案

以下函数可用于返回一个对象向量,其中为每个对象调用非默认构造函数。

template <typename T, typename ... Args>  std::vector<T> InitVector(const int n, Args ... args) {
     std::vector<T> vec;
     for(int i = 0; i < n; ++i) {
         vec.emplace_back(args ...);
     }
     return vec;
}

5 个答案:

答案 0 :(得分:6)

这里有两个解决方法。

  1. 使用list initialization

    std::vector<Obj> v2{5, 5, 5, ...}; 
    
  2. 稍后使用emplace_back插入元素。

    std::vector<Obj> v2;
    v2.reserve(10);
    for (int i=0; i<10; ++i) {
        v2.emplace_back(5);
    }
    

答案 1 :(得分:1)

我不太确定这是否可以作为解决方案,但您可以重载复制构造函数以执行预期的构造。

我尝试重载复制构造函数的想法:

#include <vector>
#include <iostream>
#include <cstdlib>

struct Obj {
    const int max_x;
    int x;

    Obj(): Obj(5) { }

    Obj(int max_x): max_x(max_x), x(rand() % max_x) { }

    Obj(const Obj &obj): Obj(obj.max_x) { }
};

int main() {
    std::vector<Obj> v1(10);     // Default constructor
    std::vector<Obj> v2(10, 5);  // Non-Default Constructor

    for(int i=0; i<10; ++i) {
        std::cout << v1[i].x << ", " << v2[i].x << std::endl;
    }
}

输出:

3, 2
1, 0
2, 4
0, 3
3, 1
0, 0
1, 1
2, 2
4, 1
1, 1

Live Demo on coliru

它更好,但退回是struct Obj中的额外成员。 : - (

答案 2 :(得分:1)

您可以使用generate_n

#include <algorithm>
#include <iterator>
std::vector<Obj> v2;
std::generate_n(std::back_inserter(v2),10, [](){return 5;});

答案 3 :(得分:1)

感谢所有快速回复。最后,我的特定问题的最佳解决方案是创建一个向量初始化函数(使用人们建议的emplace_back),它将返回所需的结果。我需要初始化很多对象向量,并希望它们是不可变的,所以这个通用解决方案可能最适合我的用例。

 #include <vector>
 #include <iostream>
 #include <cstdlib>

 template <typename T, typename ... Args>
 std::vector<T> InitVector(const int n, Args ... args) {
     std::vector<T> vec;
     for(int i = 0; i < n; ++i) {
         vec.emplace_back(args ...);
     }
     return vec;
 }

 struct Obj {
     int x;

     Obj() {
         x = rand() % 5;
     }

     Obj(int max_x) {
         x = rand() % max_x;
     }
 };

 int main() {
     const std::vector<Obj> v1(10);
     const std::vector<Obj> v2 = InitVector<Obj>(10, 5);

     for(int i=0; i<10; ++i) {
         std::cout << v1[i].x << ", " << v2[i].x << std::endl;
     }
 }

结果:

3, 2
1, 2
2, 0
0, 4
3, 3
0, 1
1, 0
2, 1
4, 2
1, 1

答案 4 :(得分:0)

我认为这些线可以帮助你

std::vector<Obj> v2;
for(int i = 0;i<10;i++)
{
    Obj s(5); // Non-Default Constructor
   v2.push_back(s); 
}