【问题标题】:C++ How do you set an array of pointers to null in an initialiser list like way?C++ 如何在初始化列表中将指针数组设置为空?
【发布时间】:2010-04-10 21:31:53
【问题描述】:

我知道您不能对数组使用初始化列表。但是,我听说过可以以类似于初始化列表的方式将指针数组设置为 NULL 的方法。

我不确定这是如何完成的。我听说指针默认设置为 NULL,但我不知道这是否在 C++ 标准中得到保证。我也不确定与正常分配相比,通过 new 运算符进行初始化是否也会产生影响。

编辑:我的意思是在头文件/构造函数初始化列表中执行此操作。我不想把它放在构造函数中,也不想使用 Vector。

【问题讨论】:

    标签: c++ arrays null pointers


    【解决方案1】:

    为了在构造函数初始化器列表中设置一个指向空值的指针数组,您可以使用() 初始化器

    struct S {
      int *a[100];
    
      S() : a() {
        // `a` contains null pointers 
      }
    };
    

    不幸的是,在当前版本的语言中,() 初始化程序是唯一可以与构造函数初始化程序列表中的数组成员一起使用的初始化程序。但显然这就是您的情况所需要的。

    () 对使用new[] 分配的数组具有相同的效果

    int **a = new int*[100]();
    // `a[i]` contains null pointers 
    

    在其他情况下,您可以使用 {} 聚合初始化器来实现相同的效果

    int *a[100] = {};
    // `a` contains null pointers 
    

    请注意,绝对没有必要在{} 之间挤压0NULL{} 的空对就可以了。

    【讨论】:

    • +1 - 顺便说一句,C 要求在初始化大括号之间至少有一个值。 C++ 添加了空大括号初始值设定项 ({ }),特别是因为没有理由让对象的默认值必须类似于 0,并且要求初始化对象的代码可能不知道合理的默认值可能是什么(特别是在模板中)。
    • 我认为 int *a = new int[100](); 创建了一个指向整数数组的指针,该数组初始化为零,这意味着 a[i] 将包含 0 并且是指向该数组中第 (i+1) 个整数的取消引用指针而不是空指针。
    • @MatthewD.Scholefield 好地方。我冒昧地解决了这个问题,因为 AnT 在其间的一年里没有。 ;) 这显示了从 C 继承的指针和数组语法在其丑陋中是如何令人困惑的,以及一两个 typedef 在这里真正有多大帮助 - 或者只是为什么不使用 new。 :P
    【解决方案2】:

    通常默认情况下不会初始化数组,但如果您显式初始化一个或多个元素,则任何剩余元素将自动初始化为 0。由于 0 和 NULL 是等价的,因此您可以初始化一个指针数组NULL 像这样:

    float * foo[42] = { NULL }; // init array of pointers to NULL
    

    【讨论】:

    • 请注意“int foo1[42] = { 1 };”仅将第一个初始化为 1,其余初始化为 0,因为默认情况下 C++ 将数组元素初始化为 0!在您的示例中,您仅将第一个元素设置为 0,其余元素默认设置为 0。
    • @amfcosta:我不确定您为什么认为答案不清楚,或者为什么它值得一票否决? OP 询问初始化指向NULL 的指针数组。
    • 请看我的评论。这是因为 int foo1[42] = { 0 };具有误导性。
    • @amfcosta:好吧,我仍然不明白它为什么会产生误导,但如果你愿意,我会补充一些说明。
    【解决方案3】:

    你可以从数组切换到std::vector并使用

    std::vector<T*> v(SIZE);
    

    这些值将由NULLs 自动初始化。这是首选的 C++ 方式。


    更新:从 C++11 开始,还有一种方法:使用

    std::array<T*, SIZE> array = {};
    

    这更像是 C 样式数组的修正版本(特别是避免动态分配),携带它的大小并且不会衰减到指针。但是,需要在编译时知道大小。

    【讨论】:

    • 除非 OP 不想要一个动态大小的数组。
    • @Billy:好吧,OP 可以忽略动态调整大小的可能性。 C++ 风格的数组通常是一件好事。
    • 如果大小在编译时已知,则内置数组更好。最好尽可能避免动态分配。 vectors 应该在编译时不知道大小常量时使用。
    • @Billy 向量与数组相比有很多很多优势,而数组与动态分配无关。例如,向量随身携带它们的大小,并且不会衰减为指针。并且应该避免动态分配 - 但在自己的代码中,而不是在库代码中。
    • @Vlad 当然,由于 C++11 和 std::array,我们可以避免动态分配,同时仍然拥有标准容器的所有其他优点,包括执行边界检查索引的能力(尽管不是自动的,因为您的评论可能会被解读为暗示)使用.at(),如vector
    【解决方案4】:

    我不确定这是怎么做到的。我听说指针默认设置为 NULL,但我不知道这是否在 C++ 标准中得到保证。
    C++ 标准不保证这一点。除非另有设置,否则内置类型(如指针)会被垃圾填充。

    我也不确定通过 new 操作符进行初始化与正常分配相比是否也会产生影响。
    “正常分配”是什么意思?如果您说的是自动变量,那么您可以这样做:

    MyType * pointers[2] = {}

    并且指针应该被初始化为NULL。

    【讨论】:

    • 指针不保证被初始化为 NULL,就像 int 在许多情况下不被初始化为 0 一样。请注意,您的示例等效于 {NULL, 0}{}(首选后者),而不是为数组中的所有项目指定一个值。
    • @RogerPate 我知道这个答案已经晚了几年,但现在已经修复了。 :)
    【解决方案5】:
    void* p[10] = { 0 };
    

    【讨论】:

    • 请注意,这只是将第一个元素显式初始化为 0,其余元素默认由 C++ 初始化为零。例如,“int foo1[42] = { 1 };”仅将第一个初始化为 1,其余初始化为 0,因为默认情况下 C++ 将数组元素初始化为 0!
    • 更重要的是,编译器将剩余的条目初始化为全位零,不能保证与空指针的表示相同。
    • @kdopen 实际上 remaining 条目是可以的;它明确给出0 这可能是一个问题 - 即,如果您明确提及0,您将获得0初始化。:S “执行零初始化[...]没有构造函数的值初始化类类型的成员,包括没有为其提供初始化器的聚合元素的值初始化。[...] 零初始化指针是其类型的空指针值,即使值空指针不是整数零。” en.cppreference.com/w/cpp/language/zero_initialization 从 C++11 开始,使用 {}
    【解决方案6】:

    如果你有一个成员数组,那么就没有办法初始化,除非它是一个静态成员。如果数组不是静态成员,则必须将其填充到构造函数的主体中。

    也就是说,使用std::vector 可能会更好。除了出于技术原因(例如您的平台无法使用标准 STL 或性能稍差)之外,std::vector 在任何和所有标准上都优于阵列。如果性能是问题,那么请确保您进行了分析并通过数字知道这是一个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2015-04-28
      • 1970-01-01
      相关资源
      最近更新 更多