Что делает двоеточие после имени конструктора С++?
Что делает оператор двоеточия ( ":" ) в этом конструкторе? Это эквивалентно MyClass(m_classID = -1, m_userdata = 0);
?
class MyClass {
public:
MyClass() : m_classID(-1), m_userdata(0) {
}
int m_classID;
void *m_userdata;
};
Ответы
Ответ 1
Это список инициализации и является частью реализации конструктора.
Подпись конструктора:
MyClass();
Это означает, что конструктор можно вызвать без параметров. Это делает его конструктором по умолчанию, т.е. Тем, который будет вызываться по умолчанию при написании MyClass someObject;
.
Часть : m_classID(-1), m_userdata(0)
называется списком инициализации. Это способ инициализировать некоторые поля вашего объекта (все они, если хотите) со значениями по вашему выбору, вместо того, чтобы оставлять их как undefined.
После выполнения списка инициализации выполняется создание тела конструктора (который окажется пустым в вашем примере). Внутри вы могли бы выполнять больше назначений, но после того, как вы ввели его, все поля уже были инициализированы - либо случайными, неуказанными значениями, либо теми, которые вы выбрали в списке инициализации. Это означает, что присваивания, которые вы выполняете в теле конструктора, не будут инициализированы, а изменения значений.
Ответ 2
Это список инициализации.
К тому моменту, когда вы попадаете в тело конструктора, все поля уже построены; если у них есть конструкторы по умолчанию, они уже вызывались. Теперь, если вы назначаете им значение в теле конструктора, вы вызываете оператор присваивания копии, что может означать освобождение и повторное получение ресурсов (например, памяти), если у объекта есть какой-либо объект.
Таким образом, в случае примитивных типов, таких как 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_;
};
Ответ 3
Он обозначает начало списка инициализации, который предназначен для инициализации переменных-членов вашего объекта.
Что касается: MyClass(m_classID = -1, m_userdata = 0);
Это объявляет конструктор, который может принимать аргументы (поэтому я мог бы создать MyClass
с помощью MyClass m = MyClass(3, 4)
, что приведет к тому, что m_classID
будет равно 3, а m_userdata
будет 4). Если бы я не передавал аргументы конструктору MyClass
, это привело бы к созданию эквивалентного объекта для версии с списком инициализации.
Ответ 4
Он сигнализирует о начале списка инициализаторов.
Также он не эквивалентен MyClass (m_classId = -1, m_userData = 0). Это попытка определить конструктор с двумя параметрами, которые имеют значения по умолчанию. Однако значения не имеют типов и не должны компилироваться вообще.
Ответ 5
Это список инициализации. В вашем примере это скорее нечто вроде этого (что-то вроде этого - не означает, что это эквивалентно во всех случаях):
class MyClass {
public:
MyClass(){
m_classID = -1;
m_userdata = 0;
}
int m_classID;
void *m_userdata;
};
Ответ 6
Это называется списком инициализации членов. Он используется для вызова конструкторов суперкласса и дает вашим переменным-членам начальное значение в момент их создания.
В этом случае он инициализирует от m_classID
до -1 и m_userData
значение NULL.
Это не совсем эквивалентно назначению в теле конструктора, потому что последний сначала создает переменные-члены, а затем присваивает им. При инициализации начальное значение предоставляется во время создания, поэтому в случае сложных объектов оно может быть более эффективным.
Ответ 7
Это не совсем оператор. Это часть синтаксиса для конструктора.
Что он говорит, так это то, что после него будет список переменных-членов и их начальные значения.
Константные члены должны быть инициализированы таким образом. Неконстанты также могут быть инициализированы здесь, если это можно сделать с помощью одного выражения. Если для инициализации элемента требуется больше кода, чем для этого, вы должны поставить фактический код между {}, чтобы сделать это.
Многим людям нравится вносить почти весь свой код конструктора в список инициализаторов. У меня есть один сотрудник, который регулярно пишет классы с несколькими экранами инициаторов, а затем помещает "{}" для кода конструктора.
Ответ 8
Это начало списка инициализации, который устанавливает переменные-члены во время построения объекта. Ваш пример "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 для получения дополнительной информации.
Ответ 9
В этом случае: Yes, ist эквивалентен, поскольку речь идет только о примитивных типах.
Если члены являются классами (structs), вы должны предпочесть список инициализации. Это происходит потому, что в противном случае объекты по умолчанию сконструированы и затем назначены.