Инициализация вектора перед main () в C ++ - PullRequest
7 голосов
/ 25 апреля 2009

Я хочу иметь возможность инициализировать вектор размером 'SIZE' перед main. Обычно я бы сделал

static vector<int> myVector(4,100);

int main() {

    // Here I have a vector of size 4 with all the entries equal to 100

}

Но проблема в том, что я хотел бы, чтобы первый элемент вектора имел определенное значение, а другой - другое значение.

Есть ли простой способ сделать это?

Ответы [ 8 ]

20 голосов
/ 25 апреля 2009

Попробуйте это:

static int init[] = { 1, 2, 3 };
static vector<int> vi(init, init + sizeof init / sizeof init[ 0 ]);

Также см. std::generate (если вы хотите инициализировать внутри функции).

10 голосов
/ 25 апреля 2009

Или просто создайте функцию и вызовите ее:

std::vector<int> init()
{
  ...
}

static std::vector<int> myvec = init()

Возможно, немного неэффективно, но это может не иметь значения для вас сейчас, и с C ++ 0x и его перемещением это будет очень быстро.

Если вы хотите избежать копирования (для C ++ 03 и более ранних версий), используйте смарт-указатель:

std::vector<int>* init() { 
    return new std::vector<int>(42);
}

static boost::scoped_ptr<std::vector<int>> myvec(init());
9 голосов
/ 26 апреля 2009

C ++ 0x разрешит списки инициализаторов для стандартных контейнеров, как агрегаты:

std::vector<int> bottles_of_beer_on_the_wall = {100, 99, 98, 97};

Очевидно, что это еще не стандарт, но он предположительно поддерживается GCC 4.4. Я не могу найти документацию для этого в MSVC, но Херб Саттер говорит, что их поддержка c ++ 0x впереди комитета ...

8 голосов
/ 25 апреля 2009

Вы можете использовать Boost, разделенный запятыми список .

7 голосов
/ 25 апреля 2009

Немного хакерский, но вы могли бы сделать это:

struct MyInitializer {
   MyInitializer() {
       myVector[0]=100;
       //...
   }
} myInitializer;  // This object gets constructed before main()
6 голосов
/ 25 апреля 2009

Вот альтернативное решение:

#include <vector>                  
static std::vector<int> myVector(4,100);

bool init()
{
    myVector[0] = 42;      
    return true;
}

bool initresult = init();

int main()                  
{
    ;
}
3 голосов
/ 27 апреля 2009

Вместо того, чтобы использовать глобальный, я бы посоветовал использовать локальную статику. Поскольку инициализация вашего вектора происходит до того, как будет введено main, любые сгенерированные исключения не будут перехвачены main. Например, у вас есть тип, который при его создании может выдать исключение:

class A {
public:
  A() { 
    // ... code that might throw an exception
  }
};

Для следующей инициализации try / catch в теле main не будет перехватывать исключение, сгенерированное конструктором, и поэтому ваша программа просто сразу же умрет, и вы, вероятно, даже не сможете использовать отладчик для поиска причина!

std::Vector<A> v(5, A());  // May throw an exception here not caught by main

int main () {
  try {
     // Exception for 'v' not handled here.
  }
  catch (...) {
  }
}

Альтернативный подход, который поймает исключение из конструктора, заключается в использовании локальной статики - которая инициализируется с использованием техники, предложенной этим ответом .

std::Vector<A> init ();  // Returns a vector appropriately initialized

std::vector<A> & getV () {
  static std::vector<A> cache = init();
  return cache;
}

int main () {
  try {
     getV().at[0];    // First call to getV - so initialization occurs here!
  }
  catch (...) {
  }
}
0 голосов
/ 25 апреля 2009

Оберните его по классу:

class SpecialVector
{
  public:
    SpecialVector()
    {
      myVector[0] = 1;
      myVector[1] = 4;
      // etc.
    }
    const vector<int> & GetVector() const
    {
      return myVector;
    }
  private:
    vector<int> myVector;
 };
 static SpecialVector SpVec;

 int main() {
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...