Есть ли способ доступа к локальной переменной во внешней области в С++?
Просто из любопытства: если у меня есть вложенные области, как в этом примере кода на С++
using namespace std;
int v = 1; // global
int main (void)
{
int v = 2; // local
{
int v = 3; // within subscope
cout << "subscope: " << v << endl;
// cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
Есть ли способ получить доступ к переменной v
со значением 2
из "промежуточной" области (ни глобальной, ни локальной)?
Ответы
Ответ 1
Вы можете объявить новую ссылку как псевдоним, например
int main (void)
{
int v = 2; // local
int &vlocal = v;
{
int v = 3; // within subscope
cout << "local: " << vlocal << endl;
}
}
Но я бы вообще избегал этой практики. Я потратил часы на отладку такой конструкции, потому что переменная отображалась в отладчике как измененная из-за области видимости, и я не мог понять, как она изменилась.
Ответ 2
Ответ: Нет. Вы не можете.
Переменная в локальной области оттеняет переменную в глобальной области, и язык предоставляет способ доступа к глобальной переменной с использованием квалифицированных имен глобального типа, как и вы. Но С++ как язык не обеспечивает доступа к промежуточной переменной.
Учитывая, что это должно было бы быть разрешено, для этого потребовалось бы много сложной обработки, представьте ситуацию с n количеством областей (вполне может быть бесконечным) и обработкой их.
Вам лучше переименовать свои промежуточные переменные и использовать те, которые будут более логичными и удобными в обслуживании.
Ответ 3
Существует два типа разрешение области видимости в С++ - унарная область действия и область класса. Не существует области действия функции или оператора "любой конкретной родительской области". Это делает невозможным решение вашей проблемы, как и вообще, потому что вы не можете ссылаться на анонимные области. Однако вы можете либо создать псевдоним, переименовать переменные, либо сделать это частью класса, что, конечно же, подразумевает изменение кода. Это самое близкое, что я могу получить без переименования в этом конкретном случае:
#include <iostream>
using namespace std;
int v = 1; // global
class Program
{
static int v; // local
public:
static int main ()
{
int v = 3; // within subscope
cout << "subscope: " << v << endl;
cout << "local: " << Program::v << endl;
cout << "global: " << ::v << endl;
}
};
int Program::v = 2;
int main ()
{
return Program::main ();
}
Существуют и другие способы, например, убедиться, что переменные не оптимизированы и находятся в стеке, тогда вы можете работать со стеком напрямую, чтобы получить значение переменной, которую вы хотите, но не позволяйте этому идти.
Надеюсь, что это поможет!
Ответ 4
Вы можете подделать это так:
#include <iostream>
using namespace std;
int v = 1;
int main()
{
int v = 2;
{
int &rv = v; // create a reference
int v = 3; // then shadow it
cout << "subscope: " << v << endl;
cout << "local: " << rv << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
return 0;
}
Интересно, что это компилируется на cygwin g++, но segfaults, если вы попытаетесь запустить его:
#include <iostream>
using namespace std;
int v = 1;
int main()
{
int v = 2;
{
int &v = v;
cout << "subscope: " << v << endl;
// cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
return 0;
}