неопределенные ссылки на встроенную функцию [duplicate]

Что такое «переменная область»?

Переменные имеют ограниченный «объем» или «места, из которых они доступны». Только потому, что вы написали $foo = 'bar'; один раз где-то в вашем приложении, это не значит, что вы можете ссылаться на $foo из всюду else внутри приложения. Переменная $foo имеет определенную область действия, в пределах которой она действительна, и только код в той же области доступа имеет доступ к переменной.

Как область, определенная в PHP?

Very просто: PHP имеет область функций . Это единственный вид разделителя областей, который существует в PHP. Переменные внутри функции доступны только внутри этой функции. Переменные вне функций доступны вне функций, но не внутри какой-либо функции. Это означает, что в PHP есть одна специальная область: глобальная область . Любая переменная, объявленная вне любой функции, находится в пределах этой глобальной области.

Пример:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;
}

$foo находится в области global , $baz находится внутри локального области внутри myFunc. Только код внутри myFunc имеет доступ к $baz. Только код вне myFunc имеет доступ к $foo. Ни один из них не имеет доступа к другому:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;

    echo $foo;  // doesn't work
    echo $baz;  // works
}

echo $foo;  // works
echo $baz;  // doesn't work

Сфера охвата и включенные файлы

Границы файлов не разделяют область :

a.php

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo;  // works!

Те же правила применяются к коду include d как применяется к любому другому коду: только отдельная область function. Для области видимости вы можете включить такие файлы, как копирование и вставка кода:

c.php

<?php

function myFunc() {
    include 'a.php';

    echo $foo;  // works
}

myFunc();

echo $foo;  // doesn't work!

В приведенном выше примере, a.php был включен внутри myFunc, любые переменные внутри a.php имеют только область локальной функции. Просто потому, что они появляются в глобальной области действия в a.php, не обязательно означают, что они есть, это фактически зависит от того, в каком контексте этот код включен / выполнен.

Что касается функций внутри функций и классов?

Каждое новое объявление function вводит новую область, это так просто.

(анонимные) функции внутри функций

function foo() {
    $foo = 'bar';

    $bar = function () {
        // no access to $foo
        $baz = 'baz';
    };

    // no access to $baz
}

classes

$foo = 'foo';

class Bar {

    public function baz() {
        // no access to $foo
        $baz = 'baz';
    }

}

// no access to $baz

Что такое область видимости?

Работа с проблемами определения области может показаться раздражающей, но ограниченная переменная область важна для написания сложных приложений! Если каждая переменная, которую вы объявляете, будет доступна везде, где бы вы ни находились, вы будете переключаться со всеми своими переменными без реального способа отслеживать, что изменит что. Есть только так много разумных имен, которые вы можете дать своим переменным, вы, вероятно, захотите использовать переменную «$name» в нескольких местах. Если бы вы могли использовать только одно уникальное имя переменной в своем приложении, вам придется прибегать к действительно сложным схемам именования, чтобы убедиться, что ваши переменные уникальны и что вы не меняете неправильную переменную из неправильной части кода.

Обратите внимание:

function foo() {
    echo $bar;
}

Если не было области, что бы сделала эта функция выше? Откуда $bar? Какое состояние оно имеет? Он даже инициализирован? Вы должны проверять каждый раз? Это не поддерживается. Это приводит нас к ...

границы границ пересечения

Правильный путь: передача переменных в и из

function foo($bar) {
    echo $bar;
    return 42;
}

Переменная $bar явно входящий в эту область действия в качестве аргумента функции. Просто глядя на эту функцию, ясно, откуда берутся ценности, с которыми она работает. Затем он явно возвращает значение. У вызывающего есть уверенность в том, что знать, с какими переменными будет работать функция, и откуда берутся его возвращаемые значения:

$baz   = 'baz';
$blarg = foo($baz);

Расширение области видимости в анонимных функциях

$foo = 'bar';

$baz = function () use ($foo) {
    echo $foo;
};

$baz();

Анонимная функция явно включает $foo из ее окружения. Обратите внимание, что это не то же самое, что область global .

Неправильный путь: global

Как уже было сказано, глобальный охват несколько особый, и функции могут явно импортировать переменные из него:

$foo = 'bar';

function baz() {
    global $foo;
    echo $foo;
    $foo = 'baz';
}

Эта функция использует и изменяет глобальную переменную $foo. Не делай это! [Если вы действительно действительно действительно знаете, что делаете, и даже тогда: не делайте этого!) [/ ​​G45]

Все вызывающие функции этой функции видят следующее:

baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!

Нет никаких указаний на то, что у этой функции есть какие-либо побочные эффекты , но это так. Это очень легко становится запутанным беспорядком, поскольку некоторые функции продолжают изменять и требуют некоторого глобального состояния. Вы хотите, чтобы функции были stateless , действуя только на их входы и возвращая определенный выход, однако много раз вы их вызываете.

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

19
задан 5gon12eder 18 February 2015 в 21:55
поделиться

1 ответ

Определение функции с static inline определяет встроенную функцию с внутренней связью. Такая функция работает «как ожидалось» из «обычных» свойств этих классификаторов: static дает внутреннюю связь, а inline делает ее встроенной. Таким образом, эта функция является «локальной» для единицы перевода и встроенной в нее.

Определение функции с помощью только inline определяет встроенную функцию с внешней связью. Однако такое определение называется встроенным определением , и оно не работает как внешнее определение для этой функции. Это означает, что, хотя эта функция имеет внешнюю связь, она будет отображаться как undefined из других единиц перевода, если только вы не предоставите для нее отдельное внешнее определение .

Определение функции с помощью extern inline определяет встроенную функцию с внешней связью, и в то же время это определение служит для внешнего определения для этой функции. Эту функцию можно вызвать из других единиц перевода.

Последние два абзаца означают, что у вас есть выбор для предоставления одного определения extern inline для встроенной функции с внешней связью или предоставления двух отдельных определений для него: один inline и другой extern. В последнем случае, когда вы вызываете функцию, компилятору разрешено выбирать одно из двух определений.

19
ответ дан AnT 21 August 2018 в 08:58
поделиться
  • 1
    Уточнение последнего абзаца: для предоставления двух отдельных определений нет необходимости (и фактически, нецелесообразно) предоставлять два функциональных органа. Вместо этого extern inline void f();, который выглядит как (и есть) объявление, имеет эффект преобразования более раннего inline void f() { ..... } как внешнего определения, а не встроенного определения для этой единицы. (Ссылка C11 6.7.4 / 7). – M.M 29 June 2015 в 07:04
Другие вопросы по тегам:

Похожие вопросы: