我有一个需要在构造函数中初始化的非指针类成员:
class Alerter {
protected:
Timer timer;
public:
Alerter(int interval);
};
然后
Alerter::Alerter(int interval) {
timer = createTimer(interval);
}
(简化代码只是为了演示问题)。
我有些怀疑和担心,timer
可能首先是使用它的无参数构造函数创建的,然后该实例会被createTimer
函数返回的内容覆盖。
这种方法有多好?可能的答案可能是:
这些假设中哪一个(或者其他假设)是最正确的?
发布于 2018-05-31 17:22:57
timer
首先是默认构造的,然后分配。当然,您可以假设默认构造Timer
或编译器优化的成本有多低,但在这里您不需要这样做,因为可以通过使用初始化器列表来防止默认构造:
Alerter::Alerter(int interval) : timer(createTimer(interval)) { }
这将会起作用,除非您的Timer
类是可复制赋值的,但不是复制可构造的,这会很奇怪。
发布于 2018-05-31 17:33:16
两个构造函数都将被调用(然后赋值也会被调用)。
我已经扩展了你的例子:
class Timer
{
public:
Timer() : m_interval(0)
{
std::cout << "Constructor withOUT parameter has been called." << std::endl;
}
Timer(int interval) : m_interval(interval)
{
std::cout << "Constructor with parameter has been called." << std::endl;
}
Timer(const Timer& timer)
{
std::cout << "Copy constructor has been called." << std::endl;
m_interval = timer.m_interval;
}
Timer(Timer&& timer)
{
std::cout << "Move constructor has been called." << std::endl;
m_interval = timer.m_interval;
}
void operator=(Timer&& timer)
{
std::cout << "Move assignment has been called." << std::endl;
m_interval = timer.m_interval;
}
private:
int m_interval;
};
class Alerter
{
protected:
Timer timer;
public:
Alerter(int interval)
{
timer = Timer(interval);
}
};
...
Alerter alerter(12);
...
输出:
Constructor withOUT parameter has been called.
Constructor with parameter has been called.
Move assignment has been called.
回答你的问题。如果成员变量只初始化一次会更好,但这不是硬规则。例如,如果计时器是一个非常复杂的对象,但默认构造函数只创建了一个虚拟对象,那么它就不会太昂贵,也不会被接受。
所以,如果你能避免,最好还是避免。使用指针是一种可能的解决方案,但请注意以下几点:
std::unique_ptr
来避免内存泄漏。https://stackoverflow.com/questions/50620813
复制相似问题