Инициализация объекта с новым оператором и без него
Если у меня есть класс Rectangle
class Rectangle{
private:
double width;
double height;
public:
void Set(double w , double l){
width = w;
height = l;
}
};
и я уменьшаю объект такой:
Rectangle *Obj;
а затем попытайтесь инициализировать его свойства:
Obj->Set(3,5);
компилятор показывает во время выполнения: The variable 'Obj' is being used without being initialized.
Проблема может быть решена с помощью:
Rectangle *Obj=new Rectangle;
Я бы спросил о причине! И почему компилятор не обнаруживает ошибок во время компиляции?
Ответы
Ответ 1
Rectangle *Obj;
просто определяет указатель для объекта класса Rectangle
. Определение указателя не резервирует память для самого объекта, только для указателя. Таким образом, если вы получаете доступ к указателю, вы, скорее всего, окажетесь по адресу в памяти, который даже не принадлежит вашему процессу. Однако компилятор не может знать, что вы не инициализировали указатель (ключевое слово здесь является псевдонимом) и, следовательно, не может выводить сообщение об ошибке.
Решение использует либо new
, как вы предполагали, или объявляет экземпляр Rectangle
следующим образом:
Rectangle Obj;
который вызовет конструктор по умолчанию. Затем вы можете установить своих участников с помощью
Obj.Set(3, 5);
Ответ 2
и я уменьшаю объект такой:
Rectangle *Obj;
Неверно, это объявляет указатель, а не объект. Указатели должны быть инициализированы либо с помощью new
, либо путем назначения им адреса существующего объекта.
Ответ 3
Ммм немного путаницы:
компилятор показывает во время выполнения: переменная 'Obj' используется без инициализации
Это то, что вы бы назвали время компиляции. Просто выправьте жаргон.
Кроме того, самым простым способом было бы
Rectangle Obj;
Obj.Set(3,5);
что достаточно для большинства сценариев, кроме динамических распределений или полиморфных контейнеров:
std::vector<Shape*> v;
v.push_back(new Rectange());
v.back()->Set(3,5);
v.push_back(new Circle());
v.back()->Set(3,5);
//
Хотя при использовании new
вы также должны помнить delete
. Это может быть довольно кошмаром (в свете исключений тоже). Я предлагаю:
std::vector<std::shared_ptr<Shape*> > v;
v.push_back(std::make_shared<Rectange>());
v.back()->Set(3,5);
v.push_back(std::make_shared<Circle>());
v.back()->Set(3,5);
Ответ 4
С Rectangle *Obj;
вы объявляете указатель на Rectangle, но вы не сказали Obj
, к которому Rectangle должен указывать. Вы можете установить или создать экземпляр Obj
позже на существующий Rectangle
или только если вам нужно.
С++ - это все, что дает вам точный контроль над вашей памятью и производительностью. На самом деле, почему он используется в некоторых встроенных средах! Автоматическое создание экземпляра Obj
создает несколько "проблем"
- Когда мы освободим
Obj
?
- Кто освобождает
Obj
?
- Как насчет влияния производительности создания
Rectangle
на кучу?
- Это среда, в которой у нас достаточно ресурсов (памяти, процессора и т.д.), чтобы создать Rectangle, особенно если он большой.
- Проводите ли вы адрес
Obj
где-нибудь, а затем создаете экземпляр его во время выполнения через какой-то сложный метод, который мы не можем проанализировать статически?
То, что вы делаете, не является синтаксической ошибкой, и это то, что компиляторы бросают ошибки при ошибках при компиляции. Анализатор (один встроен в профессионал Visual Studio 2010) может предупредить вас о том, что вы используете неинициализированную переменную, хотя это необязательно, и вам может потребоваться включить его.
Ответ 5
указатель без new объявляет что-то без памяти.
SO u нужно использовать новый с указателем.
Однако
Прямоугольник прямоугольный;
будет по умолчанию выделять память.
чтобы проверить это,
сделать конструктор в классе Rectangle, например,
void Rectangle
{
cout<<"Rectangle Constructor";
}
тогда в главном
Rectangle *rect; -->>O/P -- "Nothing"
Rectangle rect2; -->>O/P -- Rectangle Constructor
rect=new Rectangle; -->>O/P -- Rectangle Constructor
Ответ 6
почему компилятор не показывает ошибки при компиляции времени?
Потому что он синтаксически правильный. Однако такие утверждения приведут к undefined поведению, интеллектуальные компиляторы всегда выдают предупреждение.
В g++ вы можете включить такое предупреждение о компиляторе в ошибки.
Ответ 7
Прямоугольник оператора *obj
означает, что существует указатель, который будет указывать на переменную прямоугольника типа.
С помощью этого утверждения вы просто создаете указатель
не экземпляр прямоугольника объекта
для использования этого указателя вы должны сохранить адрес переменной типа прямоугольника в указателе
Два способа сделать это:
obj=new rectangle; //variable is created in the stack storage
или
rectangle r;
obj =&r; //variable is created in the heap storage