在 C++ 中的 main() 之前初始化向量

Posted

技术标签:

【中文标题】在 C++ 中的 main() 之前初始化向量【英文标题】:Initializing a vector before main() in C++ 【发布时间】:2009-04-25 11:04:59 【问题描述】:

我希望能够在 main 之前初始化一个大小为“SIZE”的向量。通常我会这样做

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

int main() 

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


但问题是我想将向量的第一项初始化为某个值,另一个初始化为另一个值。

有没有简单的方法可以做到这一点?

【问题讨论】:

这个呢:std::vector a(3, 100), &a_init((a[0] = 98, a[1] = 99, a));它将等于 "98, 99, 100" :) 只是出于好奇,你为什么需要它? 【参考方案1】:

试试这个:

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

另外,请参阅std::generate(如果您想在函数中初始化)。

【讨论】:

这不仅是最明显的方式,也是最快最清晰的方式。 +1(至少如果其他项目都为零) 不,这将给出一个 3 项向量(没有额外的元素),但为此,它非常整洁。【参考方案2】:

或者只是创建一个函数并调用它:

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());

【讨论】:

【参考方案3】:

C++0x 将允许标准容器的初始化列表,就像聚合一样:

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

显然还不是标准的,但据称它受 GCC 4.4 的支持。我在 MSVC 中找不到它的文档,但是 Herb Sutter 一直在说他们的 c++0x 支持领先于委员会......

【讨论】:

【参考方案4】:

您可以使用Boost's comma-separated list。

【讨论】:

【参考方案5】:

有点老套,但你可以这样做:

struct MyInitializer 
   MyInitializer() 
       myVector[0]=100;
       //...
   
 myInitializer;  // This object gets constructed before main()

【讨论】:

hackish,而且有点危险,因为您无法在 main 之前捕获异常,但我在这些情况下也是如此。 @Nils:实际上,vector 类提供了一个基于迭代器的 ctor,它可以与数组耦合用于这类事情。更安全,IMO。【参考方案6】:

这里是替代解决方案:

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

bool init()

    myVector[0] = 42;      
    return true;


bool initresult = init();

int main()                  

    ;

【讨论】:

有趣...有没有可能不浪费布尔空间? 是的,但不是真的。您可以尝试将 initcall 嵌入某处,但这会“隐藏”它: int somevalue = (init(), 42); 另请注意,不推荐将 static 作为“内部”链接的通知程序(即仅在翻译单元内)。请改用匿名命名空间。【参考方案7】:

与其使用全局变量,我建议最好使用局部静态变量。由于向量的初始化发生在输入 main 之前,因此抛出的任何异常都不会被 main 捕获。比如说你有一个类型,当它被构造时可能会抛出异常:

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

对于下面的初始化,main 体中的 try/catch 不会捕捉到构造函数抛出的异常,所以你的程序会直接死掉,你甚至可能无法使用调试器来查找原因!

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 (...) 
  

从构造函数捕获异常的另一种方法是使用本地静态 - 使用此 answer 建议的技术进行初始化。

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 (...) 
  

【讨论】:

【参考方案8】:

用一个类包装它:

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() 
 

【讨论】:

全局静态是不好的......如果可以的话,不要使用它们!无法捕获异常,valgrind 认为是泄漏,如果应用程序退出时出现异常,很难调试!

以上是关于在 C++ 中的 main() 之前初始化向量的主要内容,如果未能解决你的问题,请参考以下文章

C++中向量初始化的性能

C++:全局变量和static变量初始化

编译多个 C++,得到未初始化的向量

main之前初始化流程

用向量 c++ 中的指针成员初始化对象

类中的 C++ 类作为自定义向量(如何初始化?)