Search code examples
c++arrayscompiler-explorer

high performance 'proper' c++ alternative to variable length array


I am writing a function which requires an array to be created at runtime. The array will be of small size so I am not worried about unsafe code, however, I want to write 'proper' code. As such I am considering three alternatives:

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

Using Compiler Explorer to compare them with -O3. The results were as such:

  1. 12 instructions, 0 calls to new
  2. 21 instructions, 1 call to new
  3. 118 instructions, 2+ calls to new

Am I missing an optimisation for std::vector<> or is the 'proper' c++ way slower or have I entirely missed a way of coding this?

edit: I forgot to delete the heap-allocated array

Test code:

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);
}

code 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;
}

code 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);
}

Solution

  • There are a few issues in the code, that may be leading you astray in the comparison.

    1. new char(len) allocates a single char, initialized with the value len. You'd be after new char[len] to allocate len chars. There should be a matching delete [], too.
    2. The std::vector<char> object is passed to populate_array by value, making a copy (and consequently not actually populating the array you want), and similarly for compute_result. These copies will engender new allocations. Passing by reference would be appropriate here.
    3. Without using a custom allocator, std::vector will value-initialize all its elements. Effectively, it means that every element in this vector is set to zero. This is not performed by new char[len].

    VLAs are not part of C++, but may be provided as an extension. While in this instance, for small len, the compiler has the option of allocating the space for the array on the stack, they are probably best avoided because of their non-standard nature; even in C, they are not required to be supported.