Как смоделировать переменную отслеживания ссылки на член в C ++ / CLI? - PullRequest
1 голос
/ 07 января 2010

Это будет очень глупый вопрос, но возможно ли сделать следующее в C ++ / CLI?

// C++/CLI
public ref class Managed
{
    public:
        array<double>^ m_data;
        Managed(array<double>^% data) : m_data(data)
        {
        }

        void bar(int x)
        {
            System::Array::Resize(m_data, x);
        }
};
// C#
static void Main(string[] args)
{
    double [] d = new double[10];
    Foo.Managed f = new Foo.Managed(d);
    f.bar(5);
}

Так, что после вызова f.bar (5) из Main, Main :: d и f.m_data - это один и тот же «перераспределенный» массив? Я пробовал с неуправляемыми ссылками, указателями, pin_ptr и т. Д., Но ничего. Есть идеи? Если это просто невозможно, есть ли причина?

Используя оператор отслеживания ссылок (%), я мог бы сделать это, если бы я изменил размер в конструкторе, это то, что заставило меня пытаться.

Это возможно в C ++ с использованием ссылок, к сожалению, я не знаю, как преобразовать массив ^ в массив ^, и я не могу использовать массив ^% в качестве члена:

class Foo{
public:
    double *& m_data;
    Foo(double*& data): m_data(data)
    {
    }

    void bar(int x)
    {
        delete m_data;
        m_data = new double[x];
    }

    ~Foo(){
        delete [] m_data;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{

    double* data = new double[10];

    Foo f(data);
    std::cout << &data << "\n" << &f.m_data << "\n";
    f.bar(5);
    std::cout << &data << "\n" << &f.m_data;
    getchar();
    return 0;
}

1 Ответ

1 голос
/ 07 января 2010

Это невозможно, поскольку ссылки хранятся по значению: то есть CLR не поддерживает поля-члены by-ref. (Эрик Липперт обсуждает, почему здесь (вокруг второго списка пунктов маркера).) Итак, хотя d передается по ссылке в конструктор Managed, когда Managed сохраняет его в m_data, для этого требуется копия ссылки Main на массив size-10, и эта копия теперь не зависит от оригинала. Функция bar передает ссылку m_data f - которая теперь является независимой копией ссылки Main - в Array :: Resize, которая модифицирует m_data для ссылки на новый массив размера 5. Но поскольку m_data является независимой копией, это не влияет на Main.d - это все равно относится к массиву размера 10.

Возможной альтернативной стратегией является инкапсуляция ссылки на массив в небольшой класс shim, и вместо этого Main создает (и принимает Foo.Managed) экземпляр класса shim. Тогда bar может изменить размер массива, на который указывает прокладка. Поскольку Main.d и f.m_data по-прежнему будут ссылками на одну и ту же прокладку (и, таким образом, будут иметь одну ссылку на реальный массив), Main.d будет видеть массив с измененным размером (через прокладку).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...