initialize const char[] as non-static class member

Viewed 554
class foo {
  public:
    const char name[100];

    foo(const char name[]) : name(name) {};
};

int main(){
  foo("test");

  return 0;
}

Does not compile. How do I initialize const char[] non-static class member?

2 Answers

You have different option, depending on what you want to achieve.

arrays in C++ are strange beasts, they do not behave like most other types, in particular they decay to pointers and do not have copy-constructors (unless wrapped in a structure/class).

foo(const char name[]) does not take an array by value/by copy, it takes a pointer (yes, the syntax is confusing).

Thus name(name) is trying to initialize an array with a pointer. If this would compile, it would make it super-easy to overflow the stack by accident, as there is no guarantee that the pointer name points to an array that is long at most 100 elements.

Solution 1

Use a more suitable construct - use a string.

From your snippet, it seems you want to store a piece of text (variable named name, initialisation with a string-literal...), so a std::string or other string-like class (even const char*) is a better construct.

class foo {
  public:
    std::string name;

    explicit foo(std::string name_) : name(name_) {};
};
    
    int main(){
      foo("test");
    }

Solution 2

Use a better array

If you really need to store/copy an array, consider using std::array (since c++11)

#include <array>

class foo {
   public:
     std::array<char, 100> name;

    explicit foo(std::array<char, 100> name_) : name(name_) {};
};

int main(){
    foo(std::array<char, 100>{"test"});
}

Solution 3

Pass the array by const-ref.

There are use--cases where you really want to use an array. In this case you need to pass the value by reference, and copy the content with std::initializer_list (since c++14, but it's possible to emulate in c++11)

#include <utility>
    
class foo {
  template <std::size_t... PACK1>
  explicit foo(const char (&name_)[100], std::index_sequence<PACK1...>)
    : name{ name_[PACK1]... }
  {}

  const char name[100];

  public:
  explicit foo(const char (&name_)[100])
    : foo(name_, std::make_index_sequence<100>{})
  {}
    
};
    
    int main(){
        const char hello[100] = "hello!";
        foo f = foo(hello);
    }

const char (&arr)[100] is an array of length 100 passed by const-reference. As arrays do not have copy-constructors, we need to use index_sequence to initilize all members.

Solution 4

Use pointers and initialize the array in 2 phases.

Passing the array by const-reference means you need to create such a big array beforehand, and that you cannot pass a string literal which length is not exactly 101 (because of terminatig \0).

#include <cstring>
    
class foo {
  const char name[100];
public:
  // constructor requires copy... unsure if needs to be so
  explicit foo(const char* name_)
  {
      std::copy(name_, name_ + std::strlen(name_), name);
  }
};
    
int main(){
    const char test[100] = "test!";
    foo f = foo(test);
}

i would sugest to use a std::string if you are using c++, but if the const char [] is a must, here is the solution, basically you just copy some portion of the shortest string to the array of size 100, leaving unfilled the extra space(ie: name will result in name = ['t','e','s','t','\0',...] https://www.cplusplus.com/reference/cstring/memcpy/

Related