我正在从结构C转向OOP C++,:在C++中声明/定义构造函数时,我经常发现" "符号作为运算符的特殊用法.我粗略地理解了这种风格的使用,但是有人用这个构造函数定义向我解释了精确的编程技术.
例如:1
class time_stamp
{
public:
time_stamp(time &t_time)
: m_time(t_time)
{}
~time_stamp()
{
m_time.update(); // as soon as I'm destroyed, update the time
}
private:
time &m_time;
};
Run Code Online (Sandbox Code Playgroud)
例如:2
class threaded_class
{
public:
threaded_class()
: m_stoprequested(false), m_running(false)
{
pthread_mutex_init(&m_mutex);
}
~threaded_class()
{
pthread_mutex_destroy(&m_mutex);
}
/** Some other member declarations */
}
Run Code Online (Sandbox Code Playgroud)
请解释我:在以下2个例子time_stamp(time &t_time) : m_time(t_time){}和下面的代码行中使用" "
threaded_class(): m_stoprequested(false), m_running(false)
{
pthread_mutex_init(&m_mutex);
}
Run Code Online (Sandbox Code Playgroud)
冒号字符:用于表示构造函数成员初始值设定项列表.在这里,您可以初始化类的成员或调用基类构造函数.
C++标准n3337 12.6.2 § 3:
mem-initializer-list可以使用表示该基类类型的任何class-or-decltype初始化基类.
C++标准n3337 12.6.2 § 7:
mem-initializer中的expression-list或braced-init-list用于根据8.5的初始化规则初始化指定的子对象(或者,在委托构造函数的情况下,完成类对象)以进行直接初始化.
例:
class Foo {
int a;
};
Run Code Online (Sandbox Code Playgroud)
如果你希望a在调用构造函数之后整数具有确定的值,你必须a在构造函数中给出这个值.有两种选择:
在构造函数体中
Foo::Foo() {
a = 70;
}
Run Code Online (Sandbox Code Playgroud)在它的成员初始化列表中
Foo::Foo() : a( 70) {
}
Run Code Online (Sandbox Code Playgroud)它始终是合法的,永远不会低于构造函数体内的赋值,并且通常更有效.关于初始化列表非常重要的是它允许直接初始化类成员,省略受此类进程约束的成员的默认构造.
正如Scott Myers在他的"Effective C++"中指出的那样,如果你没有为类成员指定一个初始化参数,那么它的默认构造函数将被调用.当您稍后在类构造函数中对其执行赋值时,您将调用operator=成员变量.这将对成员函数进行两次调用:一次用于默认构造函数,另一次用于赋值.您可以通过指定初始值设定项来省略第一个调用.正如Scott Myers在他的"Effective C++"中所指出的那样:"从纯粹实用的角度来看,有时候必须使用初始化列表.特别是,const参考成员可能只是初始化,从未被分配".
(至少)同样重要的是,成员不会按照它们在初始化列表中的出现顺序进行初始化,而是按照在类中声明的顺序进行初始化.记住这一点,以避免错误
/* trying to allocate very large block of memory
as a result of initializing a vector with
uninitialized integer: std::vector<int> v( N)
*/
class SearchEngine {
std::vector<int> v;
int N;
explicit SearchEngine( std::vector<int> const& keys)
: N( keys.size()), v( N), {
Run Code Online (Sandbox Code Playgroud)
C++标准n3337 8.5.4 § 1:
列表初始化是从braced-init-list初始化对象或引用.这样的初始化程序称为初始化程序列表,列表的逗号分隔的初始化程序子句称为初始化程序列表的元素.初始化列表可以为空.列表初始化可以在直接初始化或复制初始化上下文中进行; 直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化.[注意:可以使用列表初始化 - 作为变量定义中的初始化程序(8.5)
- 作为新表达式中的初始值设定项(5.3.4)
- 在退货声明中(6.6.3)
- 作为函数参数(5.2.2)
- 作为下标(5.2.1)
- 作为构造函数调用的参数(8.5,5.2.3)
- 作为非静态数据成员的初始化程序(9.2)
- 在mem-initializer中(12.6.2)
- 在作业的右侧(5.17)
[例如:
int a = {1};
std :: complex z {1,2};
new std :: vector {"once","on","a","time"}; // 4个字符串元素
f({"Nicholas","Annemarie"}); //传递两个元素的列表
return {"Norah"}; //返回一个元素的列表
int*e {}; //初始化为零/空指针
x =双{1}; //显式构造一个double
std :: map anim = {{"bear",4},{"cassowary",2},{"tiger",7}};
- 结束例子] - 结束说明]
| 归档时间: |
|
| 查看次数: |
3562 次 |
| 最近记录: |