2012-08-03 6 views
7

Ich brauche eine tiefe Kopie eines (realen) Array in Fortran (90), aber bin mir nicht sicher, wie man genau einen bekommt, da ich nicht vollständig verstehe, wie Referenzen funktionieren. Intuitiv würde ich erwarten, dass dies mir bekommen, was ich will:Deep-Array-Kopie in Fortran

do i=1,n 
    b(i) = a(i) 
end do 

Es wurde jedoch vor kurzem mich darauf hingewiesen, dass b(1:n) = a(1:n) auf den Code entspricht oben. Intuitiv würde ich erwarten, dass b(1:n) = a(1:n) lediglich bewirkt, dass die Referenz b(1:n) auf den Speicherort a(1:n) im Speicher zeigt.

Ist b(1:n) = a(1:n) eine tiefe Kopie? Warum? Was passiert mit den zugrunde liegenden Referenzen im Gegensatz zu b = a?

Antwort

13

Die drei Möglichkeiten, wie Sie für das Kopieren von Arrays erwähnen, die do Schleife, b(1:n) = a(1:n) und b = a, sind alle gleichwertig sind; Sie kopieren den Inhalt des Arrays a in das Array b. a und b sind einfach Arrays, keine Phantasie-Zeiger oder irgendetwas und so ist die Zuordnung a = b im Grunde das gleiche wie der mathematische Ausdruck. Es gibt keine Magie mit Referenzen (die der Benutzer wissen muss), weshalb Fortran eine ziemlich direkte Sprache zu lernen ist. Sie können Zeiger-Arrays in Fortran haben, aber das ist ein ganz anderes Problem.

M Metcalf und J Reid Fortran 90/95 erklärt ist immer eine gute Referenz für die Beratung auf Fortran Sprachfunktionen. Von Seite 48:

3,11 Array Zuordnung

durch intrinsische Zuordnung kann ein Array-Expression kann auf eine Feldvariable der gleichen Form zugeordnet werden, die als ob jedes Element der Expressions interpretiert wurden zugewiesen zu dem entsprechenden Element der Variablen. Zum Beispiel mit den Erklärungen

real, dimension(10, 20) :: a 

Die Zuordnung

a = a + 1.0 

a(i,j) von a(i,j) + 1.0 für i=1,2..,10 und j=1,2,..,20 ersetzt.

Beachten Sie auch, dass ein Skalar Ausdruck zu einem Array zugeordnet werden kann, in welchem ​​Fall der Wert saclar all Array-Elemente ausgestrahlt wird.

In Bezug darauf, wie dies alles tatsächlich implementiert ist, was ist, was ich denke, Sie fahren mit Ihrer Frage, das ist völlig durch den Fortran-Standard nicht spezifiziert. Diese Art von Sache ist nicht spezifiziert, damit Compiler-Autoren tun können, was auch immer sie für Optimierungen wollen. In der Zuweisung a = b ist die Reihenfolge, in der die Elemente b in a kopiert werden, vom Standard nicht spezifiziert, so dass unterschiedliche Compiler dies auf verschiedene Arten tun können. Alles, was Sie wissen müssen, ist, dass für diese Frage, a und b keine Zeiger sind, dann sind a und b unterschiedliche Arrays und das Ändern eines Elements von einem ändert nicht das entsprechende Element des anderen. Es ist also ein Sinn, a=b ist eine "tiefe Kopie" und Sie können sich das vorstellen, als ob Sie alle Elemente in b an den Speicherort von a kopieren würden.

+0

@IanH Das ist nicht etwas, über das ich so viel weiß, also konzentrierte ich mich nur auf Arrays in meiner Antwort. Es wäre interessant zu sehen, dass ein Beispiel für abgeleitete Typen nicht der Fall ist, wenn Sie eine Antwort posten möchten. – Chris

+0

Entschuldigung für dieses Geschwätz, es war eine unvollendete Gedankenblase, die ich für die Frage irrelevant fand (da das Poster speziell REAL-Variablen erwähnt). Mir war nicht einmal bewusst, dass es gepostet wurde. – IanH

+1

'b (1: n) = a (1: n)' und 'b = a' sind nicht äquivalent. Erstere prüft beispielsweise nicht auf eine notwendige Umverteilung. –

6

a = b kopiert das gesamte Array b in a. Wenn Sie nur einen Teil des Arrays haben möchten, der größer als n ist, können Sie die Indexnotation a (1: n) = b (1: n) verwenden. Das ist Fortran 90 - es ist eine höhere Sprache als FORTRAN 77. Wir können sagen, dass "a = b" eine Kopie ist und keinen Zeiger a mit Ziel b assoziiert, weil diese Anweisung den Operator "=" verwendet. Die Zeigerverknüpfung verwendet =>.

Edit: durch Kopie, macht es ein Duplikat, mit wahrscheinlich den gleichen Maschinencode wie Ihre do-Schleife. Die Zeigerassoziation erstellt eine Referenz, ohne die do-Schleife auszuführen, um alle Arrayelemente zu duplizieren.

Siehe http://en.wikipedia.org/wiki/Fortran_95_language_features

+1

Wie kopiert es es? Indem man die Referenz von "a" auf die Position von "b" in dem Speicher repositioniert oder indem man eine Kopie aller Elemente in "b" auf die Position von "a" im Speicher verschiebt? – astay13

+2

@ astay13, Fortran ist nicht Java oder C#. Es hat keine Referenzen. Es hat Zeiger, aber diese benutzen spezielle Syntax, um zu assoziieren, wie M.S. B. darauf hingewiesen hat ('=>' statt '='). 'gfortran' zum Beispiel implementiert eine Array-Kopie entweder mit' memcpy' (bitweise Speicherkopie, sehr schnell) oder mit versteckten 'DO'-Loops, abhängig vom Kontext. –

+0

@HristoIliev, ja, die Frage kommt, weil Java meine erste Sprache ist, also bin ich daran gewöhnt zu denken, dass '=' als Referenz verwendet wird. – astay13