【问题标题】:Initializing a vector before main() in C++在 C++ 中的 main() 之前初始化向量
【发布时间】: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" :)
  • 只是出于好奇,你为什么需要它?

标签: c++ stl static vector


【解决方案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 认为是泄漏,如果应用程序退出时出现异常,很难调试!
          猜你喜欢
          • 2013-02-16
          • 2015-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-05
          • 2018-09-30
          相关资源
          最近更新 更多