require_once
и include_once
оба требуют, чтобы система сохранила журнал того, что уже включалось/требовалось. Каждый *_once
вызов означает проверять тот журнал. Таким образом, существует определенно [приблизительно 1 113] дополнительная работа, сделанная там, но достаточно к вреду скорость целого приложения?
... Я действительно сомневаюсь относительно него... Не, если Вы не находитесь на [1 114] действительно старые аппаратные средства или выполнение его партия .
, Если Вы делающие тысячи из *_once
, Вы могли бы сделать работу сами более легким способом. Для простых приложений просто удостоверившись Вы только включали его, как только должен быть достаточными, но если Вы все еще добираетесь, переопределяют ошибки, Вы могли что-то вроде этого:
if (!defined('MyIncludeName')) {
require('MyIncludeName');
define('MyIncludeName', 1);
}
я буду лично придерживаться с эти *_once
операторы, но на глупом миллионе сравнительного теста передачи, Вы видите различие между двумя:
php hhvm
if defined 0.18587779998779 0.046600103378296
require_once 1.2219581604004 3.2908599376678
10-100Г — медленнее с require_once
и любопытно, что require_once
по-видимому медленнее в [1 111]. Снова, это только относится к Вашему коду, если Вы работаете *_once
тысячи времен.
<?php // test.php
$LIMIT = 1000000;
$start = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
if (!defined('include.php')) {
require('include.php');
define('include.php', 1);
}
$mid = microtime(true);
for ($i=0; $i<$LIMIT; $i++)
require_once('include.php');
$end = microtime(true);
printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);
<час> <?php // include.php
// do nothing.
Главный недостаток - все. Прямые объявления - это компромисс, позволяющий сэкономить время компиляции и позволить вам иметь циклические зависимости между объектами. Однако цена заключается в том, что вы можете использовать тип только как ссылки и ничего не можете сделать с этими ссылками. Это означает, что нельзя наследовать, передавать его как значение, не использовать вложенный тип или typedef в этом классе и т. Д. Это все большие недостатки.
Конкретная проблема уничтожения, о которой вы говорите, заключается в том, если вы только пересылаете объявить тип и случайно удалить его только в модуле, поведение не определено, и ошибка не будет.
Например:
class A;
struct C
{
F(A* a)
{
delete a; // OUCH!
}
}
Microsoft C ++ 2008 не вызовет деструктор и выдаст следующее предупреждение:
warning C4150: deletion of pointer to incomplete type 'A'; no destructor called
: see declaration of 'A'
Таким образом, вы должны сохранять бдительность, что не должно быть проблемой, если вы рассматриваете предупреждения как ошибки.
Из стандарта C ++:
5.3.5 / 5:
«Если удаляемый объект имеет неполный тип класса на момент удаления, и весь класс имеет нетривиальный деструктор или функция освобождения, поведение не определено. "