Что делает в этом конструкторе оператор двоеточия (":")? Это эквивалент MyClass(m_classID = -1, m_userdata = 0);
?
class MyClass {
public:
MyClass() : m_classID(-1), m_userdata(0) {
}
int m_classID;
void *m_userdata;
};
Что делает в этом конструкторе оператор двоеточия (":")? Это эквивалент MyClass(m_classID = -1, m_userdata = 0);
?
class MyClass {
public:
MyClass() : m_classID(-1), m_userdata(0) {
}
int m_classID;
void *m_userdata;
};
Это список инициализации, который является частью реализации конструктора.
Подпись конструктора:
MyClass();
Это означает, что конструктор можно вызывать без параметров. Это делает его конструктором по умолчанию, т. Е. Тем, который будет вызываться по умолчанию, когда вы напишете MyClass someObject;
.
Часть : m_classID(-1), m_userdata(0)
называется список инициализации. Это способ инициализировать некоторые поля вашего объекта (все, если хотите) значениями по вашему выбору, вместо того, чтобы оставлять их неопределенными.
После выполнения списка инициализации выполняется тело конструктора (которое в вашем примере оказывается пустым). Внутри него вы можете выполнять больше назначений, но как только вы его введете, все поля уже будут инициализированы - либо случайными, неуказанными значениями, либо теми, которые вы выбрали в своем списке инициализации. Это означает, что назначения, которые вы выполняете в теле конструктора, будут не инициализацией, а изменением значений.
Это список инициализации.
К тому времени, когда вы попадете в тело конструктора, все поля уже созданы; если у них есть конструкторы по умолчанию, они уже были вызваны. Теперь, если вы присваиваете им значение в теле конструктора, вы вызываете оператор присваивания копии, что может означать освобождение и повторное получение ресурсов (например, памяти), если у объекта они есть.
Таким образом, в случае примитивных типов, таких как int, нет никаких преимуществ по сравнению с назначением их в теле конструктора. В случае объектов, у которых есть конструктор, это оптимизация производительности, поскольку она позволяет избежать двух инициализаций объекта вместо одной.
Список инициализации необходим, если одно из полей является ссылкой, потому что ссылка никогда не может быть нулевой, даже в короткий промежуток времени между построением объекта и телом конструктора. Следующее вызывает ошибку C2758: 'MyClass :: member_': должен быть инициализирован в списке инициализаторов базы конструктора / члена
class MyClass {
public :
MyClass(std::string& arg) {
member_ = arg;
}
std::string& member_;
};
Единственно правильный способ:
class MyClass {
public :
MyClass(std::string& arg)
: member_(arg)
{
}
std::string& member_;
};
MyClass m = { arg };
тоже подойдет.
- person Johannes Schaub - litb; 13.08.2009
Он обозначает начало списка инициализаторов, предназначенного для инициализации переменных-членов вашего объекта.
As to: MyClass(m_classID = -1, m_userdata = 0);
Это объявляет конструктор, который может принимать аргументы (так что я мог бы создать MyClass
, используя MyClass m = MyClass(3, 4)
, что приведет к тому, что m_classID
будет 3, а m_userdata
равно 4). Если бы я не передавал конструктору MyClass
аргументов, это привело бы к созданию объекта, эквивалентного версии со списком инициализаторов.
Он сигнализирует о начале списка инициализаторов.
Также он не эквивалентен MyClass (m_classId = -1, m_userData = 0). Это попытка определить конструктор с двумя параметрами, которые имеют значения по умолчанию. Однако в значениях отсутствуют типы, и он вообще не должен компилироваться.
Это список инициализации. В вашем примере это скорее примерно так (что-то вроде этого - не означает, что это эквивалентно во всех случаях):
class MyClass {
public:
MyClass(){
m_classID = -1;
m_userdata = 0;
}
int m_classID;
void *m_userdata;
};
Это называется списком инициализации членов. Он используется для вызова конструкторов суперкласса и присвоения вашим переменным-членам начального значения во время их создания.
В этом случае он инициализирует m_classID
значением -1 и m_userData
значением NULL.
Это не совсем эквивалентно назначению в теле конструктора, потому что последний сначала создает переменные-члены, а затем присваивает им. При инициализации начальное значение предоставляется во время создания, поэтому в случае сложных объектов оно может быть более эффективным.
Это не совсем оператор. Это часть синтаксиса конструктора.
В нем говорится, что за ним будет список переменных-членов и их начальных значений.
Таким образом должны быть инициализированы постоянные члены. Здесь также можно инициализировать неконстантные значения, если это можно сделать с помощью одного выражения. Если для инициализации члена требуется больше кода, чем требуется, для этого нужно поместить реальный код между {}.
Многим людям нравится помещать почти весь свой код конструктора в список инициализаторов. У меня есть коллега, который регулярно пишет классы с несколькими экранами инициализаторов, а затем помещает "{}" в код конструктора.
Это начало списка инициализаторов, который устанавливает переменные-члены во время создания объекта. Ваш пример «MyClass (m_classID = -1, m_userdata = 0);» невозможно, поскольку вы не определили правильный конструктор, и вы все равно не сможете получить доступ к переменным-членам в списке параметров ... у вас может быть что-то вроде:
MyClass( int classId = -1, void* userData = 0 ) : m_classID(classId), m_userdata(userData) {}
Список инициализаторов считается лучше, чем:
MyClass( int classId = -1, void* userData = 0 ) {
m_classID = classId;
m_userdata = userData;
}
Google для получения дополнительной информации.
В этом случае: Да, ist эквивалентен, потому что речь идет только о примитивных типах.
Если члены являются классами (структурами), вам следует предпочесть список инициализации. Это связано с тем, что в противном случае объекты создаются по умолчанию, а затем назначаются.