将 const char[] 初始化为非静态类成员

Posted

技术标签:

【中文标题】将 const char[] 初始化为非静态类成员【英文标题】:initialize const char[] as non-static class member 【发布时间】:2020-12-06 04:51:46 【问题描述】:
class foo 
  public:
    const char name[100];

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

int main()
  foo("test");

  return 0;

不编译。如何初始化const char[]非静态类成员?

【问题讨论】:

memcpy 是你的朋友。 char name[100] 是 C 时代错误,在 C++ 中使用 std::aray<char, 100> std::string 看起来更合适。数组真的很愚蠢。它们是为解决 1970 年的问题而设计的,并且可以很好地完成工作,但是如果您想要从 Java 或 Python 等较新设计的语言中获得的那种魔力,您需要使用 C++ library containers 您将不得不将该数组移动到一个单独的类中,该类有自己的构造函数采用char const*,别无他法(没有邪恶的const_cast)。 【参考方案1】:

您有不同的选择,具体取决于您想要实现的目标。

C++ 中的数组是奇怪的野兽,它们的行为不像大多数其他类型,特别是它们会衰减为指针并且没有复制构造函数(除非包装在结构/类中)。

foo(const char name[]) 不按值/按副本获取数组,它采用指针(是的,语法令人困惑)。

因此name(name) 正在尝试使用指针初始化数组。 如果这样可以编译,那么意外溢出堆栈会非常容易,因为不能保证指针名称指向的数组最多包含 100 个元素。

解决方案 1

使用更合适的构造 - 使用字符串。

从您的 sn-p 看来,您似乎想要存储一段文本(名为 name 的变量,使用字符串文字进行初始化...),因此是 std::string 或其他类似字符串的类(甚至const char*) 也是一个更好的结构。

class foo 
  public:
    std::string name;

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

解决方案 2

使用更好的数组

如果确实需要存储/复制数组,请考虑使用std::array(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");

解决方案 3

通过 const-ref 传递数组。

在某些用例中,您确实想使用数组。 在这种情况下,您需要通过引用传递值,并使用 std::initializer_list 复制内容(从 c++14 开始,但可以在 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 (&amp;arr)[100] 是一个由 const-reference 传递的长度为 100 的数组。 由于数组没有复制构造函数,我们需要使用index_sequence来初始化所有成员。

解决方案 4

使用指针并分两个阶段初始化数组。

通过 const-reference 传递数组意味着您需要事先创建一个如此大的数组,并且您不能传递长度不完全为 101 的字符串文字(因为 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);

【讨论】:

【参考方案2】:

如果您使用 c++,我建议使用 std::string,但如果必须使用 const char [],这是解决方案,基本上您只需将最短字符串的一部分复制到大小为 @987654324 的数组中@,留下未填充的额外空间(即:name 将导致name = ['t','e','s','t','\0',...] https://www.cplusplus.com/reference/cstring/memcpy/

【讨论】:

以上是关于将 const char[] 初始化为非静态类成员的主要内容,如果未能解决你的问题,请参考以下文章

class中static总结-静态成员函数和静态成员变量

静态成员变量初始化 C++

C/C++ 将 char 数组初始化为 const char*

C++面向对象-static、const

从 const char 数组初始化为动态分配的 const char 数组

类定义中的静态数据成员初始化?