Есть ли способ получить доступ к локальной переменной во внешней области в C ++? - PullRequest
14 голосов
/ 02 декабря 2011

Просто из любопытства: если у меня есть вложенные области видимости, как в этом примере кода C ++

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 из "промежуточного звена""область действия (ни глобальная, ни локальная)?

Ответы [ 4 ]

17 голосов
/ 02 декабря 2011

Вы можете объявить новую ссылку как псевдоним, например,

int main (void)
{
    int v = 2; // local 
    int &vlocal = v;
    {
        int v = 3; // within subscope
        cout << "local: " << vlocal  << endl; 
    }
}

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

7 голосов
/ 02 декабря 2011

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

Учитывая, что это должно быть разрешено, потребуется много сложной обработки, представьте себе ситуацию с n количеством областей (вполне может быть бесконечной) и обработкой этих.

Вам лучше переименовать промежуточные переменные и использовать те, которые были бы более логичными и простыми в обслуживании.

5 голосов
/ 02 декабря 2011

Существует два типа разрешения области действия операторы в C ++ - унарная область действия и область действия класса. Не существует ни области действия функции, ни оператора разрешения «какой-либо конкретной родительской области». Это делает невозможным решение вашей проблемы в целом, поскольку вы не можете ссылаться на анонимные области. Однако вы можете создать псевдоним, переименовать переменные или сделать его частью класса, что, конечно, подразумевает изменение кода. Это самое близкое, что я могу получить без переименования в данном конкретном случае:

#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 ();
}

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

Надеюсь, это поможет!

2 голосов
/ 02 декабря 2011

Вы можете подделать это так:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...