我有一个非指针类成员,我需要在构造函数中初始化:
class Alerter {
protected:
Timer timer;
public:
Alerter(int interval);
};
然后
Alerter::Alerter(int interval) {
timer = createTimer(interval);
}
(简化代码只是为了演示问题)。
我有一些疑问和顾虑timer
可能是首先使用其无参数构造函数创建的,稍后该实例将被createTimer
函数返回的内容覆盖。
这种做法有多好?可能的答案可能是:
哪些假设(或其他可能的东西)最正确?
答案 0 :(得分:11)
timer
首先是默认构造的,然后分配。当然,您可以假设Timer
对于默认构造有多便宜或者编译器优化,但是在这里您不需要这个,因为可以通过使用初始化列表来阻止默认构造:
Alerter::Alerter(int interval) : timer(createTimer(interval)) { }
除非你的Timer
类是可复制的,但不是可复制构造的,否则这将是有效的。这将是奇怪的。
答案 1 :(得分:3)
将调用两个构造函数(然后也分配)。
我扩展了你的例子:
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.
回答你的问题。如果成员变量只初始化一次会更好,但这不是一个硬性规则。例如,如果Timer是一个非常复杂的对象,但默认构造函数只创建一个虚拟对象,那么它并不太昂贵且可以接受。
所以,如果你能避免,最好避免。使用指针是一种可能的解决方案,但请注意以下几点:
std::unique_ptr
来避免内存泄漏。