Какова область видимости переменной в основной функции C++?

Скажем, у меня есть основная функция на C++ с объявленным вектором:

int main()
{
  vector<int> arr (10, 5);

  for (auto num : arr)
  {
    cout << num << endl;
  }
}

Насколько я понимаю, переменная доступна в любом месте от того места, где она была определена, вплоть до закрывающей скобки среды, в которой она была определена. Итак, здесь arr доступен где угодно в main (), и, таким образом, он находится в области видимости цикл for.

Однако теперь скажем, что я определяю функцию и вызываю ее в main.

int main()
{
  vector<int> arr (10, 5);
  func();
}

void func()
{
  arr.push_back(1);
}

Теперь arr не определен в func (). Я понимаю, почему это так, поскольку, строго говоря, массив нигде не определен в области действия функции func (). Я понимаю, что нам нужно передать arr в качестве параметра функции func (), чтобы это работало. Но это противоречит моему пониманию области видимости, определенной выше, где arr доступен где угодно в main, а поскольку func () вызывается в main, почему у него нет доступа к arr?

Дополнительно: я уже некоторое время занимаюсь разработкой на JS, поэтому я привык к этому шаблону вложенных функций:

function main() {
  let a = 5;
  function nested() {
    console.info(a)
  }
}

И здесь во вложенной функции доступен a.

"Теперь arr не определено в func ()" - да, конец истории. Нет, он не определяется волшебным образом только потому, что вы вызываете его откуда-то, где существует arr. И фрагмент javascript не имеет значения, потому что он использует совершенно другую языковую функцию, вложенную функцию, а не вызываемую / вызываемую функцию.
luk2302 04.04.2021 20:12

Вы видите именно то, что есть прицел. arr известен в main и известен, когда вы вызываете func, но не в самом func. Вот почему вы должны передать его как аргумент функции func, как вы сами предложили.

Philip Stuyck 04.04.2021 20:15

В C++ есть похожая конструкция: auto nested = [&] { std::cout << a; };. Как видите, это не то же самое, что вызов функции, точно так же, как вложенные функции JS не совпадают с вызовами функций JS.

chris 04.04.2021 20:17
"... поскольку func () вызывается в main ..." - но func не существует в main, поэтому не может видеть имена, определенные в main.
Richard Critten 04.04.2021 20:17

В Javascript, если вы вызываете функцию в main, переменные main также не будут доступны неявно в этой функции. Если вам нужна застежка, используйте ее.

Silvio Mayolo 04.04.2021 20:18

Что касается вложенности, вы можете использовать глобальную переменную, которая достигнет того же самого, но не идите по этому пути, это плохая практика. javascript не является компилируемым языком и во всех отношениях отличается от C++. Не сравнивайте яблоки с грушами.

Philip Stuyck 04.04.2021 20:18

LOL есть много ответов на этот вопрос.

CEPB 04.04.2021 20:19

@CEPB LOL2 полные правила для неквалифицированного имени искать en.cppreference.com/w/cpp/language/unqualified_lookup

Richard Critten 04.04.2021 20:20

@RichardCritten спасибо за ссылку !!! Но этот вопрос: why I cannot access variable x, где x находится в основном, и они обращаются к нему в foo(), здесь настолько распространен, что это забавно !!!!

CEPB 04.04.2021 20:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
66
1

Ответы 1

В C++ видимость переменной находится внутри {}, где она объявлена. Можно сделать глобальную переменную, но вам нужно объявить ее в верхней части файла. Если вы хотите написать функцию тела, вам нужно сначала сказать, что функция будет существовать.

void func();
vector<int> arr (10, 5);
int main()
{
  func();
}

void func()
{
  arr.push_back(1);
}

Редактировать:

Но это плохая практика, рекомендуется использовать ссылку.

void func(vector<int> &arr);

int main()
{
  vector<int> arr (10, 5);
  func(arr);
}

void func(vector<int> &arr)
{
  arr.push_back(1);
}

Ош, только что узнал на днях, не делайте этого на C++, это плохая практика !!!! Прочтите это: rules.sonarsource.com/cpp/tag/pitfall/RSPEC-5421

CEPB 04.04.2021 20:27

@CEPB да, вы правы, но я думаю, что новичку легче сделать глобально и изучить основы, чем использовать указатели, возможно, с первого дня кода

7Adrian 04.04.2021 20:48

+1, надеюсь, вы не против, что я отредактирую ваш ответ. Параметр указателя - foo (int *a), ссылка - foo (int &a). Основное различие между ними в том, что вы можете изменить адрес *a, а не &a.

CEPB 04.04.2021 20:59

Другие вопросы по теме