bod*_*ydo 137 c++ initialization member-initialization
假设我有私人承包商,客人一类ptr,name,pname,rname,crname和age.如果我自己不初始化会怎么样?这是一个例子:
class Example {
private:
int *ptr;
string name;
string *pname;
string &rname;
const string &crname;
int age;
public:
Example() {}
};
Run Code Online (Sandbox Code Playgroud)
然后我做:
int main() {
Example ex;
}
Run Code Online (Sandbox Code Playgroud)
如何在ex中初始化成员?指针会发生什么?做string和int获得0 intialized默认构造函数string()和int()?参考会员怎么样?const引用怎么样?
我还应该知道什么?
有谁知道涵盖这些案例的教程?也许在一些书中?我可以在大学的图书馆访问很多C++书籍.
我想学习它,所以我可以编写更好的(无bug)程序.任何反馈都会有帮助!
Tyl*_*nry 181
代替显式初始化,类中成员的初始化与函数中局部变量的初始化相同.
对于对象,将调用其默认构造函数.例如,对于std::string,默认构造函数将其设置为空字符串.如果对象的类没有默认构造函数,那么如果没有显式初始化它将是编译错误.
对于原始类型(指针,整数等),它们不会被初始化 - 它们包含先前在该存储器位置发生的任何垃圾.
对于引用(例如std::string&),初始化它们是非法的,并且您的编译器将抱怨并拒绝编译此类代码.必须始终初始化引用.
因此,在您的特定情况下,如果未明确初始化它们:
int *ptr; // Contains junk
string name; // Empty string
string *pname; // Contains junk
string &rname; // Compile error
const string &crname; // Compile error
int age; // Contains junk
Run Code Online (Sandbox Code Playgroud)
Dan*_*ien 26
首先,让我解释一下mem-initializer-list是什么.甲MEM-初始化列表是逗号分隔的列表MEM-初始化 s,其中每个MEM-初始化是其成员的名字,随后(,接着是表达式列表,随后进行).的表达式列表是构件是如何构造的.例如,在
static const char s_str[] = "bodacydo";
class Example
{
private:
int *ptr;
string name;
string *pname;
string &rname;
const string &crname;
int age;
public:
Example()
: name(s_str, s_str + 8), rname(name), crname(name), age(-4)
{
}
};
Run Code Online (Sandbox Code Playgroud)
用户提供的无参数构造函数的mem-initializer-list是name(s_str, s_str + 8), rname(name), crname(name), age(-4).这个mem-initializer-list意味着该name构件由构造函数初始化,该std::string构造函数接受两个输入迭代器,该rname成员使用引用进行初始化name,该crname成员使用const-reference 初始化name,并age使用该值初始化该成员-4.
每个构造函数都有自己的mem-initializer-list,成员只能按照规定的顺序初始化(基本上是在类中声明成员的顺序).因此,的成员Example:只能在顺序进行初始化ptr,name,pname,rname,crname,和age.
如果未指定成员的mem-initializer,则C++标准会说:
如果实体是类型类型的非静态数据成员...,则实体默认初始化(8.5)....否则,实体未初始化.
这里,因为name是类类型的非静态数据成员,所以如果name在mem-initializer-list中没有指定初始化器,则默认初始化.所有其他成员Example都没有类类型,因此它们没有初始化.
当标准表明它们没有被初始化时,这意味着它们可以具有任何价值.因此,因为上面的代码没有初始化pname,所以它可以是任何东西.
请注意,您仍然必须遵循其他规则,例如必须始终初始化引用的规则.不初始化引用是一个编译器错误.
小智 10
您还可以在声明它们时初始化数据成员:
class another_example{
public:
another_example();
~another_example();
private:
int m_iInteger=10;
double m_dDouble=10.765;
};
Run Code Online (Sandbox Code Playgroud)
我几乎完全使用这种形式,虽然我读过一些人认为它是"糟糕的形式",也许是因为它最近才引入 - 我认为在C++ 11中.对我来说这更合乎逻辑.
新规则的另一个有用方面是如何初始化本身是类的数据成员.例如,假设这CDynamicString是一个封装字符串处理的类.它有一个构造函数,允许您指定其初始值CDynamicString(wchat_t* pstrInitialString).你可能很好地将这个类用作另一个类中的数据成员 - 比如一个封装了一个windows注册表值的类,在这种情况下它存储了一个邮政地址.要对其编写的注册表项名称进行"硬编码",请使用大括号:
class Registry_Entry{
public:
Registry_Entry();
~Registry_Entry();
Commit();//Writes data to registry.
Retrieve();//Reads data from registry;
private:
CDynamicString m_cKeyName{L"Postal Address"};
CDynamicString m_cAddress;
};
Run Code Online (Sandbox Code Playgroud)
请注意,保存实际邮政地址的第二个字符串类没有初始化程序,因此在创建时将调用其默认构造函数 - 可能会自动将其设置为空字符串.
这取决于类的构造方式
回答这个问题需要理解 C++ 语言标准中的一个巨大的 switch case 语句,而对于普通人来说很难有直觉。
举一个简单的例子来说明事情有多困难:
主程序
#include <cassert>
int main() {
struct C { int i; };
// This syntax is called "default initialization"
C a;
// i undefined
// This syntax is called "value initialization"
C b{};
assert(b.i == 0);
}
Run Code Online (Sandbox Code Playgroud)
在默认初始化中,您可以从:https: //en.cppreference.com/w/cpp/language/default_initialization开始,我们转到“默认初始化的效果是”部分并开始 case 语句:
然后,如果有人决定值初始化,我们转到https://en.cppreference.com/w/cpp/language/value_initialization “值初始化的效果是”并开始 case 语句:
= delete)这就是为什么我强烈建议您永远不要依赖“隐式”零初始化。除非有强有力的性能原因,否则请显式初始化所有内容,无论是在构造函数上(如果您定义了),还是使用聚合初始化。否则,你会给未来的开发人员带来非常非常大的风险。
如果示例类在堆栈上实例化,则未初始化的标量成员的内容是随机的且未定义的.
对于全局实例,未初始化的标量成员将被清零.
对于本身是类实例的成员,将调用它们的默认构造函数,因此将初始化您的字符串对象.
int *ptr; //未初始化的指针(如果全局则为零)string name; //构造函数调用,用空字符串初始化string *pname; //未初始化的指针(如果全局则为零)string &rname; //如果您无法初始化此错误,则会出现编译错误const string &crname; //如果您无法初始化此错误,则会出现编译错误int age; //标量值,未初始化和随机(或全局归零)未初始化的非静态成员将包含随机数据。实际上,它们只会拥有分配给它们的内存位置的值。
当然,对于对象参数(如string),对象的构造函数可以进行默认初始化。
在你的例子中:
int *ptr; // will point to a random memory location
string name; // empty string (due to string's default costructor)
string *pname; // will point to a random memory location
string &rname; // it would't compile
const string &crname; // it would't compile
int age; // random value
Run Code Online (Sandbox Code Playgroud)