高性能的“适当”C++替代可变长度数组

8

我正在编写一个需要在运行时创建数组的函数。该数组将非常小,因此我不担心不安全代码,但是我想编写“适当”的代码。因此,我考虑了三种替代方案:

  1. char array[len];
  2. char *array = new char[len];
  3. std::vector<char> array(len);

使用Compiler Explorer以 -O3 选项进行比较,得到如下结果:

  1. 12 条指令,0 次调用 new
  2. 21 条指令,1 次调用 new
  3. 118 条指令,2 次或更多次调用 new

我是否错过了针对 std::vector<> 的优化,还是“适当”的c++方式速度较慢,或者我完全忽略了一种编码方式?

编辑:我忘记删除堆分配的数组

测试代码:

code 1:

#include <string.h>

void populate_array(char* arr);
int compute_result(char* arr);

int str_to_arr(const char* str)
{
    auto len = strlen(str);
    char array[len];
    populate_array(array);
    return compute_result(array);
}

代码 2:

#include <string.h>

void populate_array(char* arr);
int compute_result(char* arr);

int str_to_arr(const char* str)
{
    auto len = strlen(str);
    char* array = new char[len];
    populate_array(array);
    auto result = compute_result(array);
    delete[] array;
    return result;
}

代码 3:

#include <string.h>
#include <vector>

void populate_array(std::vector<char> arr);
int compute_result(std::vector<char> arr);

int str_to_arr(const char* str)
{
    auto len = strlen(str);
    std::vector<char> array(len);
    populate_array(array);
    return compute_result(array);
}

1
向量代码还会释放内存,而其他代码则不会。 - Richard Critten
还有unique_ptr - HolyBlackCat
2
以下是几个选项:https://godbolt.org/z/Gv1oGM。您代码中的一些错误:向量one会复制整个向量,因为您传递的是值,这与其他选项不可比较(要么按引用传递,要么传递“data()”指针)。您应该使用`new char[len]来分配len个字节的字符。在代码2中,由于您没有delete[] array`,所以存在内存泄漏。 - Artyer
boost::container::small_vector是什么?基本上,选择一个len的上限,然后你可以使用一个该大小的数组(不是VLA)。 - Marc Glisse
@fabian,这段代码在我的电脑上可以编译通过,无论是在编译器浏览器还是本地都可以。我在 Arch Linux 上使用 CMake 进行编译,我相信它使用的是g++ -std=c++20 ...以及几乎所有警告,这对我来说很有效。 - Ebony Ayers
显示剩余4条评论
1个回答

7

代码中存在一些问题,可能会让你在比较时走错方向。

  1. new char(len) 分配了一个单独的char,并用值 len 进行初始化。为了分配 len 个char,您需要使用 new char[len]。同样,还需要匹配使用 delete []
  2. std::vector<char> 对象通过值传递给了 populate_array,这将导致复制(因此实际上并没有填充您想要的数组),compute_result 同理。这些副本将导致新的分配。在这里使用按引用传递是合适的。
  3. 如果不使用自定义分配器,std::vector 将值初始化其所有元素,这意味着该向量中的每个元素都设置为零。new char[len] 则不执行此操作。

可变长度数组(VLA)不是C++的一部分,但可能作为扩展提供。虽然在此示例中,对于较小的 len,编译器有选项在堆栈上分配数组空间,但由于其非标准性,最好避免使用;即使在C中也不要求支持。


2
在这个评论的基础上,考虑使用std::vector<char> array; array.reserve(len);,然后稍后使用array.push_back(something) - Abdul Rahman Dabbour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接