使用":"符号在C++中定义构造函数

Dig*_*ode -2 c++ oop

我正在从结构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)

4pi*_*ie0 7

冒号字符:用于表示构造函数成员初始值设定项列表.在这里,您可以初始化类的成员或调用基类构造函数.

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在构造函数中给出这个值.有两种选择:

应优先通过成员启动列表进行初始化

它始终是合法的,永远不会低于构造函数体内的赋值,并且通常更有效.关于初始化列表非常重要的是它允许直接初始化类成员,省略受此类进程约束的成员的默认构造.

正如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}};

- 结束例子] - 结束说明]