【问题标题】:Is there a way to statically-initialize a dynamically-allocated array in C++?有没有办法在 C++ 中静态初始化动态分配的数组?
【发布时间】:2011-04-15 05:46:35
【问题描述】:

在 C++ 中,我可以静态初始化一个数组,例如:

int a[] = { 1, 2, 3 };

有没有一种简单的方法可以将动态分配的数组初始化为一组立即值?

int *p = new int[3];
p = { 1, 2, 3 }; // syntax error

...还是我必须手动复制这些值?

【问题讨论】:

  • 你反对什么?编写代码初始化向量的必要性?复制需要多少时间?请注意,任何初始化动态分配数组的编译器技巧都将涉及相同的复制,因为无法保证分配的内存带有正确的内容。
  • 如果性能至关重要,为什么还要动态分配?为什么要通过指针进行间接寻址?由于您无论如何都在“静态初始化”数组,所以矩阵的维度在编译时肯定是已知的吗?
  • 我不反对任何事情,只是问问。我正在使用我自己的矩阵类,它将数据存储在一个动态分配的数组中,我认为如果我可以在不手动复制数据的情况下初始化该数组,那就太好了。 :)
  • @Fred:这只是矩阵的一个测试用例,看看它是否为我提供了某些预定义输入的正确结果。在一般情况下,大小在编译时是未知的。
  • 好的,所以您可能正在使用非常大的矩阵?在这种情况下,可能存在比数组或向量更好的数据结构,具体取决于这些矩阵的性质。

标签: c++ arrays initialization c++11


【解决方案1】:

你可以在 C++0x 中:

int* p = new int[3] { 1, 2, 3 };
...
delete[] p;

但我更喜欢矢量:

std::vector<int> v { 1, 2, 3 };

如果你没有 C++0x 编译器,boost 可以帮助你:

#include <boost/assign/list_of.hpp>
using boost::assign::list_of;

vector<int> v = list_of(1)(2)(3);

【讨论】:

  • +1std::vector。有什么理由仍然使用自己的动态数组?
  • @neu:如果你甚至不信任std::vector,也许你应该完全放弃C++,转而使用汇编语言。
  • @Poni:没有必要的理由说明访问向量会比访问数组慢得多,因此任何声称否则的测试仅适用于特定的编译器、编译器选项和库。请记住,一个实现可以进行额外的检查,许多在调试模式下或选择某些编译器选项时会这样做。
  • @neuviemeporte:哪些访问器功能?如果你觉得你绝对需要保持控制,你总是可以写像int * ptr = &amp;v[0];...ptr[i]...这样的东西,因为(截至2003年)矢量内容存储保证是连续的。只要确保在矢量大小增加时更改ptr
  • @Poni:我们之前曾在 SO 上提出过这个论点,它是 NOT 正确的。看这里。 (stackoverflow.com/questions/3664272/3664349#3664349) 我们最终证明向量和内置数组之间没有区别。
【解决方案2】:

您必须明确分配动态数组的每个元素(例如,在 for 或 while 循环中)

不过,int *p = new int [3](); 语法确实会将所有元素初始化为 0(值初始化 $8.5/5)

【讨论】:

    【解决方案3】:

    为了避免无休止的 push_backs,我通常会初始化一个 tr1::array 并从结果中创建一个 std::vector(或任何其他容器标准容器);

    const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
    std::vector <T> vec(values.begin(), values.end());
    

    这里唯一的烦恼是您必须明确提供值的数量。

    这当然也可以不使用tr1::array 来完成;

    const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
    std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);
    

    虽然您不必明确提供元素的数量,但我更喜欢第一个版本。

    【讨论】:

      【解决方案4】:

      不,您不能以相同的方式初始化动态创建的数组。

      在大多数情况下,您会发现自己在静态初始化并没有真正意义的情况下使用动态分配。例如,当您有包含数千个项目的数组时。所以这通常没什么大不了的。

      【讨论】:

        【解决方案5】:

        使用辅助变量:

        const int p_data[] = {1, 2, 3};
        int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
        

        或者,一行

        int p_data[] = {1, 2, 3},  *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
        

        【讨论】:

        • 作为一般规则(也是一个养成的好习惯),你不应该在函数调用中动态分配对象(也就是说,你不应该在函数的参数中调用new )。原因是函数参数的评估顺序未指定,因此您最终可能会动态分配内存,然后另一个参数的评估可能会引发异常,然后该动态分配的对象将被泄漏。 Herb Sutter has more.
        • +1 虽然这有点神秘,只适用于 POD。
        • James McNellis,一般规则只是一般规则。他们有一个解释,以确保规则匹配案例。在这种情况下,一切正常。
        • 这个特殊情况,是的,它是“好的”;但是编写高质量的代码意味着将代码编写为众所周知的安全模式(尤其是当模式不会产生任何开销时)。这段代码不会通过任何合理的关键代码审查(或者,至少它不应该)。
        • @James:不幸的是,有些人愿意为“性能”这头圣牛牺牲每一个好的软件原则。
        【解决方案6】:

        从来没有听说过这样的事情,那太好了。

        请记住,通过这种方式在代码中初始化数组

        int a[] = { 1, 2, 3 };
        

        .....只会让您更轻松地编写代码而不是提高性能。 毕竟,无论你怎么做,CPU 都会为数组赋值。

        【讨论】:

        • 该行不生成任何代码...这是编译时初始化。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多