【问题标题】:Initialisation of static vector静态向量的初始化
【发布时间】:2011-04-11 17:48:33
【问题描述】:

我想知道是否有比下面的初始化静态向量“更好”的方法?

class Foo
{
    static std::vector<int> MyVector;
    Foo()
    {
        if (MyVector.empty())
        {
            MyVector.push_back(4);
            MyVector.push_back(17);
            MyVector.push_back(20);
        }
    }
}

这是一个示例代码:)

push_back() 中的值是独立声明的;不在数组之类的。

编辑:如果不可能,请告诉我:)

【问题讨论】:

  • 很想看看 C++0x 的人会说什么。我认为类定义之外的类似 Foo::MyVector {4,17,20} 的东西是可能的。

标签: c++ static-members stdvector


【解决方案1】:

在 C++03 中,最简单的方法是使用工厂函数:

std::vector<int> MakeVector()
{
    std::vector v;
    v.push_back(4);
    v.push_back(17);
    v.push_back(20);
    return v;
}

std::vector Foo::MyVector = MakeVector(); // can be const if you like

“返回值优化”应该意味着数组被填充到位,而不是复制,如果这是一个问题。或者,您可以从数组初始化:

int a[] = {4,17,20};
std::vector Foo::MyVector(a, a + (sizeof a / sizeof a[0]));

如果你不介意使用非标准库,可以使用 Boost.Assignment:

#include <boost/assign/list_of.hpp>

std::vector Foo::MyVector = boost::list_of(4,17,20);

在 C++11 或更高版本中,您可以使用大括号初始化:

std::vector Foo::MyVector = {4,17,20};

【讨论】:

  • +1 用于新语言功能(统一初始化语法 ftw)。
  • 这个函数是个坏主意,因为只有一个静态向量要填充。
  • @Xirdus:是什么让它成为一个坏主意?如果您需要初始化一个非空数组,那么这是一种方法。
  • 我问了一些可以缩短和清除代码的东西。上面的代码(在我的某些情况下)与 #define MyMain main(int argc, char** argv) 一样有用
  • @Xirdus:不,您要求一种“更好”的方式来初始化向量。我的回答提供了一种实际初始化它的方法(而不是填充一个初始化为空的数组),它允许您(例如)初始化一个常量向量。所以它确实回答了你的问题,如果不是你认为的意思。
【解决方案2】:

通常,我有一个用于构造我使用的容器的类(例如来自 boost 的 this one),这样你就可以这样做:

const list<int> primes = list_of(2)(3)(5)(7)(11);

这样,您也可以制作静态常量,以避免意外修改。

对于静态,您可以在 .cc 文件中定义:

// Foo.h

class Foo {
  static const vector<int> something;
}

// Foo.cc

const vector<int> Foo::something = list_of(3)(5);

在 C++Ox 中,我们将有一种语言机制来执行此操作,使用初始化列表,因此您可以这样做:

const vector<int> primes({2, 3, 5, 7, 11});

here

【讨论】:

  • 我猜如果他强调这些值“不在数组中”,那么新功能也不会有多大好处。我想没有办法让它们进入某种集合或忍受重复的插入调用。
  • 我认为 list_of 是我需要的。它看起来很简单,而且我认为比多个 push_backs 更快。当我说“它们不在数组中”时,我并没有提到它们不能在一个数组中。
  • 最有可能的是,它在内部使用了多个 push_back(),因此在这个意义上它并不是“更快”。它确实避免了构造函数中的条件,这会使它更快。但是,静态初始化可能不是您的代码花费大部分时间的地方,因此优化这些部分很可能不会带来明显的收益。
【解决方案3】:

使用 C++11:

//The static keyword is only used with the declaration of a static member, 
//inside the class definition, not with the definition of that static member:
std::vector<int> Foo::MyVector = {4, 17, 20};

【讨论】:

  • 您好,这是给我的:错误:在 '=' 标记之前的声明中的限定 ID。可能是什么问题?
【解决方案4】:

你可以试试这个:

int arr[] = { 1,2,3,4,5,6,7,8,9 };
MyVector.insert(MyVector.begin(), arr, &arr[sizeof(arr)/ sizeof(*arr)]);

但它可能只在你有一个非常长的向量时才值得,而且它看起来也不是更好。但是,您摆脱了重复的 push_back() 调用。当然,如果您的值“不在数组中”,则必须先将它们放入其中,但您可以静态地(或至少是引用/指针)执行此操作,具体取决于上下文。

【讨论】:

    【解决方案5】:

    如何使用静态对象进行初始化。在它的构造函数中 可以调用对象中的静态函数来进行初始化。

    【讨论】:

    • 请详细说明或举例。
    • 创建一个只有构造函数的类声明,其中您将一个值(或多个值)推回全局/静态向量中。然后创建该类的静态实例 -> 构造函数将在 main 之前调用,并且将填充静态向量。该实例不会造成任何内存开销,因为它不包含任何成员变量。 (在你的 cpp 文件中使用一个未命名的命名空间来声明/定义/实例化助手类)
    【解决方案6】:

    通过 boost,您可以使用在 boost::assign 命名空间中定义的 +=() 运算符。

    #include <boost/assign.hpp>
    
    using namespace boost::assign;
    
    int main()
    {
        static std::vector<int> MyVector;
        MyVector += 4,17,20;
        return 0;
    }
    

    或静态初始化:

    #include <boost/assign.hpp>
    
    using namespace boost::assign;
    
    static std::vector<int> myVector = list_of(4)(17)(2);
    
    int main()
    {
        return 0;
    }
    

    甚至更好,如果您的编译器支持 C++ 11,请使用初始化列表。

    【讨论】:

    • 我可以这样做static 班级成员吗?
    • C++ 11 对此有初始化列表,或者您可以使用结构而不是类并静态初始化它们 MyStruct val = {1, 2, 3 }。否则,对于私有类成员,您必须使用构造函数。
    猜你喜欢
    • 2012-12-15
    • 1970-01-01
    • 2011-08-22
    • 2010-12-22
    • 1970-01-01
    • 2013-07-21
    • 2015-01-21
    • 2010-12-11
    相关资源
    最近更新 更多