如何通过构造函数通过成员初始化列表初始化C风格的char数组和int数组



Code-1

#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s)
{
for(int i=0; i<=4; i++)
{
p[i]=*q;
q++;
}
strcpy(str,s);
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);

return 0;
}

输出(运行平稳,但只是发出警告)

Clang-Tidy: Constructor does not initialize 
these fields: p, str

为什么会出现这种警告。我知道我在构造函数中赋值,而不是初始化,但当我创建只有int类型变量的简单类时,如果我以同样的方式赋值,它不会发出这样的警告?

代码-2

#include <iostream>
#include <cstring>
class A
{
private:
int p[5];
char str[20];
public:
A(int *q, char *s):  // just not getting how we can do this initialization
{
}
};
int main()
{
int r[5]={2, 3, 5, 7, 11};
char ch[]="bonaparte";
A a1(r, ch);

return 0;
}

有没有办法通过构造函数通过成员初始化列表初始化int类型或C-style char数组。

我知道我可以用string替换char阵列,但我想知道C-style char阵列的方法。

C++中的数组不是该语言中最友好的部分。尤其是当你让它们衰减为指针时(大小信息丢失)。所以我更喜欢使用std::array、std::vector和std::string,因为这些标准库类可以帮助您防止各种内存错误。

关于初始化问题,是的,你只能在构造函数的主体中赋值。这也是我更喜欢std::array/std::vector的另一个原因——你可以在初始化器中使用它们。我还认为:strcpy是"C"的遗留部分,在当前C++中不再使用。有趣地学习更多C++:)

#include <iostream>
//#include <cstring> // <== don't use this. (If you want to use strings in C++ use <string>
#include <vector>
#include <string>
// try to learn not to use what is called
// "magic numbers" in your source code!
// define numbers you are going to use
// 
const std::size_t int_array_size = 5;
const std::size_t string_array_size = 20;
// we don't know the length of the string yet, but we can let
// the compiler figure it out and we make a templated constructor
class A
{
public:
// pass arrays in by const, you're not supposed to 
// change their content.
A(const int (&p)[int_array_size], const char (&str)[string_array_size])
{
// I always use std::size_t for indices in arrays (not supposed to be <0)
for (/*int*/ std::size_t i = 0; i < int_array_size; i++) m_p[i] = p[i];
// don't use ::strcpy it's not "safe". It depends on correct input
// like the string having a trailing 0
for (std::size_t i = 0; i < string_array_size; i++) m_str[i] = str[i];
}
private:
int m_p[int_array_size];
char m_str[string_array_size];
};
// this is one way I would code it.
// using C++ with variable length array (so I use std::vector, for fixed length use std::array)
class B
{
public:
B(const std::vector<int>& p, const std::string& str) :
m_p{ p },
m_str{ str }
{
}
private:
std::vector<int> m_p; // or std::array<int,int_array_size>
std::string m_str;
};
int main()
{
// I prefer to use aggregate initialization (https://en.cppreference.com/w/cpp/language/aggregate_initialization)
int r[int_array_size]{ 2, 3, 5, 7, 11 };

// The next line is defined behavior. C++ standard says all remaining 
// values of ch after bonaparte will be 0
char ch[string_array_size]{ "bonaparte" };
A a1(r, ch);
B b1{ {1,2,3}, "hello world!" };
return 0;
}