8

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);
}
9
  • 1
    The vector code also frees the memory which the other code does not do. Commented Jan 10, 2021 at 11:29
  • There's also unique_ptr. Commented Jan 10, 2021 at 11:29
  • Code 1 does not compile for me and it shouldn't. The value you pass as array size needs to be a constexpr, but here clearly it isn't. Commented Jan 10, 2021 at 11:41
  • Also std::vector test case should only be doing 1 heap allocation unless there is code we are not seeing that increases it's size. Commented Jan 10, 2021 at 11:43
  • 2
    Here's a few options: godbolt.org/z/Gv1oGM. Some errors in your code: The vector one copies the entire vector because you pass by value isn't comparable to the other ones (either pass by reference or pass the data() pointer). You should be doing new char[len] to allocate len bytes of chars. You have a memory leak in code 2 since you don't delete[] array. Commented Jan 10, 2021 at 11:46

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Adding on to this comment, consider using std::vector<char> array; array.reserve(len); Then later using array.push_back(something).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.