Я знаю, что в C ++, когда вы пишете
int i;
Вы не можете делать какие-либо предположения о значении, которое будет содержать переменная, пока вы не назначите ей значение. Тем не менее, если вы пишете
int i = int();
тогда у вас есть гарантия, что i
будет 0
, Итак, мой вопрос, не является ли это на самом деле несоответствием в поведении языка? Я имею в виду, если я определил класс MyClass
и писать
MyClass myInstance;
Я могу быть уверен, что конструктор по умолчанию без параметров класса будет вызван для инициализации myInstance
(и компилятор потерпит неудачу, если его нет), потому что так работает принцип RAII. Однако, кажется, что когда дело доходит до примитивных типов, получение ресурсов больше не является инициализацией. Это почему?
Я не думаю, что изменение этого поведения, унаследованного от C, сломало бы какой-либо существующий код (есть ли в мире код, работающий на предположении, что нельзя сделать никаких предположений о значении переменной?), Поэтому главная возможная причина мне приходит в голову производительность, например, при создании больших массивов примитивных типов; но все же я хотел бы знать, есть ли официальный объяснение этому.
Благодарю.
Нет, это не противоречие.
Что если ваш класс определен как:
struct MyClass
{
int x;
float y;
char *z;
};
тогда эта строка НЕ делает то, что вы думаете:
MyClass myInstance;
Предполагая, что вышеприведенное объявлено внутри функции, оно совпадает с:
int x; //assuming declared inside a function
В C ++ типы широко делятся на 3 вида, а именно. POD, не POD, агрегаты — и между ними есть четкое различие. Пожалуйста, прочитайте о них и правилах их инициализации (на них слишком много тем. Поиск на этом сайте). Также читайте о статическая инициализация а также динамическая инициализация.
Настоящая причина, по крайней мере на начальном этапе, заключалась в том, что C ++ хотел, чтобы все
объекты, совместимые с C, ведут себя именно так, как они
будет в C. причина в C было (и до сих пор) производительность;
нулевая инициализация объектов со статическим временем жизни была бесплатной
(потому что ОС должна инициализировать всю память, которую она дает
в любом случае, по соображениям безопасности); нулевая инициализация
в противном случае стоит время выполнения. (Обоснование производительности меньше
сильны сегодня, чем были изначально, потому что компиляторов много
лучше определить, что переменная будет инициализирована
позже и подавление инициализации нуля в таких случаях;
но они все еще существуют; в частности, в таких случаях, как:
char buffer[1000];
strcpy( buffer, something );
Если требуется нулевая инициализация, я не знаю ни одного
компилятор, который сможет пропустить его здесь, даже если он
не будет необходимости.)
Если ты пишешь
int i;
тогда инициализация или нет зависит от контекста.
Отсутствие инициализации для локальной переменной только для эффективности. Для очень простой функции, которая вызывается повторно на самых низких уровнях, это может иметь значение. А C и C ++ — это языки, используемые для конструирования нижних уровней вещей.
Когда вы устанавливаете локальную переменную в функции на какое-то значение, то каждый раз, когда вызывается функция, происходит присвоение, и значение загружается в стек.
Например:
void func()
{
int i = 0; // Every time `func` is called, '0' is loaded into the stack
...
}
Это то, чего вы можете избежать, особенно потому, что языки C и C ++ также предназначены для систем реального времени, где важна каждая операция.
И, кстати, когда вы объявляете MyClass myInstance
Вы действительно можете быть уверены, что вызывается конструктор по умолчанию, но вы можете выбрать, хотите ли вы что-либо делать в этом конструкторе.
Таким образом, языки C и C ++ позволяют вам делать одинаковый выбор и для переменных примитивного типа.