Вызовите не конструктор объекта по умолчанию для каждого объекта уникально при создании вектора объектов - PullRequest
0 голосов
/ 13 июня 2018

Я пытаюсь создать вектор объектов и хотел бы, чтобы конструктор не по умолчанию вызывался уникально для каждого объекта в векторе.У меня есть упрощенный пример ниже.

В моем примере у меня есть объект с двумя конструкторами, по умолчанию (без аргументов) и не по умолчанию (1 аргумент).Когда я инициализировал вектор размером 10, используя конструктор по умолчанию (v1), конструктор вызывается 10 раз (как видно по случайным числам).Однако, когда я пытаюсь инициализировать вектор конструктором, отличным от объекта по умолчанию (v2), конструктор объекта вызывается один раз, и этот объект копируется в оставшиеся элементы в векторе (x больше не является множеством разных случайных чисел).

Можно ли инициализировать вектор из 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 голосов
/ 14 июня 2018

Спасибо за все быстрые ответы.В конце концов, лучшим решением моей конкретной проблемы было создание функции инициализации вектора (используя 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
0 голосов
/ 13 июня 2018

Вы можете использовать generate_n:

#include <algorithm>
#include <iterator>
std::vector<Obj> v2;
std::generate_n(std::back_inserter(v2),10, [](){return 5;});
0 голосов
/ 13 июня 2018

Я не совсем уверен, может ли это быть решением, но вы можете перегрузить конструктор копирования, чтобы выполнить намеченную конструкцию.

Я попробовал эту идею с перегрузкой конструктора копирования:

#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

Живая демоверсия на coliru

Это лучше, но ничьядополнительный член в struct Obj.: - (

0 голосов
/ 13 июня 2018

я думаю, что эти строки могут помочь вам

std::vector<Obj> v2;
for(int i = 0;i<10;i++)
{
    Obj s(5); // Non-Default Constructor
   v2.push_back(s); 
}
0 голосов
/ 13 июня 2018

Вот два обходных пути.

  1. Использование инициализация списка .

    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);
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...