Подтвердить что ты не робот

Почему я могу назначить struct указателем?

Почему он даже компилируется?

struct UE{
    UE(bool a = true) {  };
//  UE(){}; // if UE took no initial args and called below, gcc will complain.
};
class VA {
    protected:
            UE ue;
    public:
            VA();
};
VA::VA()
{
    ue = new UE(true); // ???why???
//  ue = new UE(); // will complain
}

Я пробовал с gcc (GCC) 4.6.2. Как я могу назначить структуру с указателем?

4b9b3361

Ответ 1

Вы сталкиваетесь с тем, что вы не отмечали свой конструктор как explicit, и поэтому его можно использовать для неявных преобразований.

new UE(true) возвращает указатель. Все указатели могут быть неявно преобразованы в bool, что приводит к true, если они не равны нулю. UE может быть неявно построено из a bool. Таким образом, указатель, возвращаемый new, преобразуется в bool, который преобразуется в UE с помощью вашего конструктора, а затем вызывается оператор назначения копирования UE. Конечно, память, выделенная new, просочилась.

Сообщение о возврате: всегда отмечайте конструкторы с одним аргументом как explicit, если вы действительно не хотите, чтобы они использовались для неявных преобразований. Под "конструктором с одним аргументом" я имею в виду тот, который можно вызвать с помощью одного аргумента. Либо потому, что у него есть один параметр, либо у него есть все и все параметры после первых аргументов по умолчанию.

Ответ 2

Существует неявное преобразование с любого указателя на bool. Следовательно, этот код неявно вызывает конструктор одиночных аргументов после преобразования указателя в значение bool

Один из способов исправить это состоит в том, чтобы сделать однозначный конструктор параметров явным.

struct UE{
    explicit UE(bool a = true) {  };
};

Это предотвратит компиляцию кода, если явно не будет вызван конструктор

Ответ 3

Любой скалярный тип может быть преобразован в логическое значение true или false в зависимости от того, равно ли оно его нулю или нет.

В этом утверждении

ue = new UE(true); 

вызывается неявно определяемый оператором присваивания копии компилятора. Поскольку выражение new UE (true) не равно нулю, оно может быть неявно преобразовано в логическое значение true. Класс UE имеет конструктор преобразования

UE(bool a = true);

который преобразует объект типа bool в объект типа UE.

Чтобы предотвратить такое использование, вы должны определить конструктор как явный

explicit UE(bool a = true);

Ответ 4

Если вы отметите явно конструктор, это не будет работать:

explicit UE( bool a = true) {  };

это потому, что есть неявное преобразование из указателя в bool, мы можем видеть, что это разрешено из стандартного раздела проекта С++ 4.12 Логические преобразования говорят (выделено мной):

Значение арифметики, неперечисленное перечисление, указатель или указатель на тип члена может быть преобразован в prvalue типа bool.