2010-01-07 1 views
1

Cela va être une question vraiment maladroite mais est-il possible de faire ce qui suit en C++/CLI?Comment simuler une variable de suivi de référence de membre en 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); 
} 

tel que, après f.bar appel (5) de Main, principal :: d et f.m_data sont le même tableau "réaffectés"? J'ai essayé avec des références non managées, des pointeurs, pin_ptr et ainsi de suite mais rien. Des idées? Si ce n'est pas possible, y a-t-il une raison? En utilisant l'opérateur de suivi de référence (%), je pourrais le faire si je devais redimensionner dans le constructeur, c'est ce qu'il m'a fait essayer.

Ceci est possible en C++ en utilisant les références, malheureusement, je ne sais pas comment lancer un tableau^à un tableau^& ni je peux utiliser le tableau ^% en tant que membre:

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; 
} 

Répondre

1

Ce n'est pas possible , car les références sont stockées par valeur: c'est-à-dire que le CLR ne prend pas en charge les champs de membres by-ref. (Eric Lippert discusses why here (around the second list of bullet points).) Donc bien que d soit passé par référence dans le constructeur de Managed, quand Managed stocke ceci dans m_data, cela prend une copie de la référence de Main au tableau de taille 10, et cette copie est maintenant indépendante de l'original. La fonction bar transmet la référence m_data de f - qui est une copie maintenant indépendante de la référence de Main - dans Array :: Resize, qui modifie m_data pour faire référence à un nouveau tableau de taille 5. Mais parce que m_data est une copie indépendante, cela n'affecte pas Main.d - qui fait toujours référence au tableau de taille 10.

Une stratégie alternative possible consiste à encapsuler la référence de tableau dans une petite classe de shim, et avoir à la place une instance de la classe shim à la place de create (et Foo.Managed accept). Ensuite, la barre pourrait redimensionner le tableau pointé par la cale. Puisque Main.d et f.m_data seraient toujours des références au même shim (et partageraient ainsi une seule référence au tableau réel), Main.d verrait le tableau redimensionné (à travers le shim).

+0

Mais la référence que je passe est un tracker/ref. Comme, par exemple, devrais-je redimensionner le tableau dans le constructeur, le tableau dans main serait également modifié. – Anzurio

+0

Mais le CLR ne prend pas en charge les membres du référentiel. (Je devrais mettre à jour ma réponse pour dire ceci plutôt que "les références sont passées par la valeur.") M_data est une vieille référence simple, pas une référence à une référence: la référence à une référence est seulement pertinente dans le fait de la transmettre dedans hors de la méthode du constructeur. – itowlson

+0

J'ai mis à jour par la réponse pour rendre plus clair quand la référence devient une "copie indépendante". Désolé l'original était trompeur. – itowlson

Questions connexes