Gibt es eine Funktion zum Kopieren eines Arrays in C / C ++?

88

Ich bin ein Java-Programmierer, der C / C ++ lernt. Ich weiß also, dass Java eine Funktion wie System.arraycopy () hat. um ein Array zu kopieren. Ich habe mich gefragt, ob es in C oder C ++ eine Funktion zum Kopieren eines Arrays gibt. Ich konnte nur eine Implementierung zum Kopieren eines Arrays finden, indem ich for-Schleife, Zeiger usw. Verwendete. Gibt es eine Funktion, mit der ich ein Array kopieren kann?

J L
quelle
6
man memmoveundman memcpy
Tim Cooper
27
Nicht benutzen memcpy, benutzen std::copy. Wenn Ihr Typ einen aussagekräftigen Kopierkonstruktor hat, memcpywird er das Falsche tun.
Ed S.
10
Versuchen Sie tatsächlich, C und C ++ gleichzeitig zu lernen? Sie sind sehr unterschiedliche Sprachen.
Ferruccio
1
Nun, ich habe ein bisschen C gelernt und jetzt habe ich vor kurzem angefangen, C ++ zu lernen. Nach dem, was ich aus einer Online-Ressource gelesen habe, dachte ich, C ++ sei nur eine Sprache mit vielen zusätzlichen Funktionen zur C-Sprache.
JL
5
Ich sage das, weil es noch niemand erwähnt hat: In C ++ sollten Sie in fast allen Fällen std :: vector verwenden. Es gibt Fälle, in denen auch andere Container nützlich sind, aber in den meisten Fällen ist std :: vector die beste Option. Verwenden Sie in C ++ keine Raw-Arrays und vermeiden Sie std :: array, es sei denn, dies ist erforderlich.
Skalli

Antworten:

78

Seit C ++ 11 können Sie Arrays direkt kopieren mit std::array:

std::array<int,4> A = {10,20,30,40};
std::array<int,4> B = A; //copy array A into array B

Hier ist die Dokumentation zu std :: array

taocp
quelle
@XAleXOwnZX: Das gleiche wie bei jedem anderen Typ, der die Kopierzuweisung unterstützt. B = A.
Swalog
2
Ich denke, die Funktion ist das Kopieren der Speicheradresse von A nach B. Wenn ich versuche, die Elementwerte von A nach B zu kopieren, ohne die Speicheradresse von B zu ändern. Wie kann ich das machen?
Aaron Lee
@Aaron_Lee: Ich habe es gerade getestet und es kopiert die Elemente wirklich in ein Array an einem separaten Speicherort. Die Array-Klasse hat offensichtlich eine eigene Überladung für den Zuweisungsoperator.
Dave Rove
2
Ihr merkt, dass in diesen beiden Codezeilen keine Zuweisungsoperatoren vorkamen, oder? Das ist der Kopierkonstruktor, der aufgerufen wird, obwohl die Notation wie der Zuweisungsoperator aussieht.
Albino Cordeiro
134

Da Sie nach einer C ++ - Lösung gefragt haben ...

#include <algorithm>
#include <iterator>

const int arr_size = 10;
some_type src[arr_size];
// ...
some_type dest[arr_size];
std::copy(std::begin(src), std::end(src), std::begin(dest));
Ed S.
quelle
2
erreur: 'begin' ist kein Mitglied von 'std'
David 天宇 Wong
23
@ David 天宇 Wong: Sie verwenden einen alten Compiler oder haben den Header nicht eingefügt. Es ist in<iterator>
Ed S.
9
Vielleicht solltest du sagen, welche Includes du brauchst. Ist Kopie in <algorithm>?
Jerry Jeremiah
14
Ich frage nur, weil, wenn Sie erklären müssten, dass std :: begin in <iterator> war, dies bedeutet, dass die Leute nicht std :: googeln, um herauszufinden, in welchem ​​Header es sich befindet, so dass es unwahrscheinlich ist, dass sie std :: copy für dasselbe googeln Grund. Es ist eine bessere Antwort, wenn niemand etwas fragen muss, das nur in Kommentaren beantwortet wird. Vielleicht hätte ich die Antwort einfach bearbeiten sollen, anstatt Sie dazu aufzufordern.
Jerry Jeremiah
3
Sie können beginnen (src) in src und Ende (src) in src + arr_size ändern
Calvin
81

Wie andere bereits erwähnt haben, würden Sie in C verwenden memcpy. Beachten Sie jedoch, dass dies eine Rohspeicherkopie ausführt. Wenn Ihre Datenstrukturen also einen Zeiger auf sich selbst oder aufeinander haben, zeigen die Zeiger in der Kopie weiterhin auf die Originalobjekte.

In C ++ können Sie auch , memcpywenn Sie Ihre Array Mitglieder POD sind (die im wesentlichen Typen sind , die Sie auch unverändert in C verwendet haben könnten), aber im Allgemeinen memcpywird nicht erlaubt sein. Wie bereits erwähnt, ist die zu verwendende Funktion std::copy.

Allerdings sollten Sie in C ++ selten Raw-Arrays verwenden. Stattdessen sollten Sie entweder eine der Standardcontainer verwenden ( std::vectorist in der Nähe von einer eingebauten in Reihe, und auch ich denke , die am nächsten Java - Arrays - näher als einfachen C ++ Arrays, in der Tat - aber std::dequeoder std::listbesser geeignet in einigen Fällen) oder, wenn Sie C ++ 11 verwenden, std::arraydas den integrierten Arrays sehr nahe kommt, aber wie andere C ++ - Typen eine Wertsemantik aufweist. Alle hier genannten Typen können durch Zuordnung oder Kopierkonstruktion kopiert werden. Darüber hinaus können Sie mithilfe der Iteratorsyntax von opne zu einem anderen (und sogar von einem integrierten Array) "crosskopieren".

Dies gibt einen Überblick über die Möglichkeiten (ich gehe davon aus, dass alle relevanten Header enthalten sind):

int main()
{
  // This works in C and C++
  int a[] = { 1, 2, 3, 4 };
  int b[4];
  memcpy(b, a, 4*sizeof(int)); // int is a POD

  // This is the preferred method to copy raw arrays in C++ and works with all types that can be copied:
  std::copy(a, a+4, b);

  // In C++11, you can also use this:
  std::copy(std::begin(a), std::end(a), std::begin(b));

  // use of vectors
  std::vector<int> va(a, a+4); // copies the content of a into the vector
  std::vector<int> vb = va;    // vb is a copy of va

  // this initialization is only valid in C++11:
  std::vector<int> vc { 5, 6, 7, 8 }; // note: no equal sign!

  // assign vc to vb (valid in all standardized versions of C++)
  vb = vc;

  //alternative assignment, works also if both container types are different
  vb.assign(vc.begin(), vc.end());

  std::vector<int> vd; // an *empty* vector

  // you also can use std::copy with vectors
  // Since vd is empty, we need a `back_inserter`, to create new elements:
  std::copy(va.begin(), va.end(), std::back_inserter(vd));

  // copy from array a to vector vd:
  // now vd already contains four elements, so this new copy doesn't need to
  // create elements, we just overwrite the existing ones.
  std::copy(a, a+4, vd.begin());

  // C++11 only: Define a `std::array`:
  std::array<int, 4> sa = { 9, 10, 11, 12 };

  // create a copy:
  std::array<int, 4> sb = sa;

  // assign the array:
  sb = sa;
}
Celtschk
quelle
1
Das memcpy-Beispiel ist falsch; Quelle und Ziel werden umgeschaltet.
AT - Student
1
Eigentlich war das nicht der einzige Fehler im memcpyBeispiel; Die Größe war auch falsch. Ich habe es jetzt behoben, danke.
Celtschk
warum schreibst du die ganze Zeit std anstatt nur den Namespace von std zu benutzen ???
Schwarz
kannst du nicht memcpy machen (b, a, sizeof a); auch?
Rodi
Ein Java-Array ist eher ähnlich std:arrayals ähnlich std::vector, da es eine feste Größe hat.
Bart van Heukelom
17

Sie können die memcpy(), verwenden

void * memcpy ( void * destination, const void * source, size_t num );

memcpy()kopiert die Werte von numBytes von der Position, auf die gezeigt wird, sourcedirekt in den Speicherblock, auf den gezeigt wird destination.

Wenn sich das destinationund sourceüberlappen, können Sie verwenden memmove().

void * memmove ( void * destination, const void * source, size_t num );

memmove()kopiert die Werte von numBytes von der Position, auf die gezeigt wird, sourcein den Speicherblock, auf den gezeigt wird destination. Das Kopieren erfolgt so, als ob ein Zwischenpuffer verwendet würde, sodass sich Ziel und Quelle überlappen können.

Deepu
quelle
3
Muss hier -1 sein. Das OP fragt speziell nach einer C ++ - Lösung und diese Antwort sagt nichts über die Situationen aus, in denen memcpyes falsch ist, dh das Kopieren von Bytes ist unzureichend.
Ed S.
2
@ Eds. Falls Sie es nicht bemerkt haben, fragt das OP jetzt nach einer C- oder C ++ - Lösung.
autistisch
4
Als ich antwortete, fragte das OP nach C / C ++ - Lösungen, obwohl ich persönlich glaube, dass "C / C ++" eine Beleidigung für beide Sprachen ist. :)
Deepu
Fair genug, ich wusste nicht, dass es sich ändert. Vielleicht hat es das sogar früher gesagt und ich habe es verpasst. -1 entfernt.
Ed S.
2
@EdS Ich dachte, es wären 2 Minuten, aber unabhängig davon, wann diese Antwort veröffentlicht wurde, bezog sich die Frage sowohl auf C als auch auf C ++. Selbst wenn ich mich geirrt habe und die Frage irgendwann nur noch C ++ lautete, war die Ablehnung nicht gerechtfertigt.
Jim Balter
16

Verwendung memcpyin C, std::copyin C ++.

user541686
quelle
Für ein kleines Array gehe ich davon aus, dass weder ein Funktionsaufruf-Overhead anfällt ( memcpysollte ein Compiler intrinsisch sein)?
Wcochran
@Mehrdad Ich habe nichts anderes gesagt; Ich mache nur einen Kommentar. Und ich habe es auch nicht abgelehnt.
MD XF
10

In C können Sie verwenden memcpy. In C ++ std::copyaus dem <algorithm>Header verwenden.

Pete Becker
quelle
8

Ich mag die Antwort von Ed S., aber dies funktioniert nur für Arrays mit fester Größe und nicht, wenn die Arrays als Zeiger definiert sind.

Also die C ++ - Lösung, bei der die Arrays als Zeiger definiert sind:

    const int bufferSize = 10;
    char* origArray, newArray;
    std::copy(origArray, origArray + bufferSize, newArray);

Hinweis : buffersizeMit 1 muss nicht abgezogen werden:

1) Kopiert alle Elemente im Bereich [zuerst, zuletzt] vom ersten bis zum letzten - 1

Siehe: https://en.cppreference.com/w/cpp/algorithm/copy

Trommel
quelle
3

In C ++ 11 können Sie dies Copy()für Standardcontainer verwenden

template <typename Container1, typename Container2>
auto Copy(Container1& c1, Container2& c2)
    -> decltype(c2.begin())
{
    auto it1 = std::begin(c1);
    auto it2 = std::begin(c2);

    while (it1 != std::end(c1)) {
        *it2++ = *it1++;
    }
    return it2;
}
STERBLICH
quelle
Aus Leistungsgründen ist es besser std::end, die Schleife aus der Schleife zu ziehen (c1 ändert oder macht die Iteratoren während der Schleife nicht ungültig, sodass das Ende nicht neu berechnet werden muss).
Celtschk
3

Ich gebe hier zwei Möglichkeiten zum Bewältigen von Arrays für C- und C ++ - Sprache. memcpy und copy sind beide unter C ++ verwendbar, aber copy ist für C nicht verwendbar. Sie müssen memcpy verwenden, wenn Sie versuchen, das Array in C zu kopieren.

#include <stdio.h>
#include <iostream>
#include <algorithm> // for using copy (library function)
#include <string.h> // for using memcpy (library function)


int main(){

    int arr[] = {1, 1, 2, 2, 3, 3};
    int brr[100];

    int len = sizeof(arr)/sizeof(*arr); // finding size of arr (array)

    std:: copy(arr, arr+len, brr); // which will work on C++ only (you have to use #include <algorithm>
    memcpy(brr, arr, len*(sizeof(int))); // which will work on both C and C++

    for(int i=0; i<len; i++){ // Printing brr (array).
        std:: cout << brr[i] << " ";
    }

    return 0;
}
FaridLU
quelle
3
using namespace std;ist eine schlechte Praxis . Benutze es niemals. Verwenden Sie anstelle von cplusplus.com cppreference.com, das eine viel bessere und aktuellere Dokumentation des Standards enthält. Das stdio.hÄquivalent in C ++ ist cstdio, verwenden Sie das stattdessen. Darüber hinaus ist der Code ziemlich nicht idiomatisch C ++. Ich denke, es wäre viel klarer, wenn Sie separate Lösungen für C und C ++ vorgestellt hätten.
Tambre
3

Fügen Sie einfach die Standardbibliothek in Ihren Code ein.

#include<algorithm>

Die Arraygröße wird als bezeichnet n

Dein altes Array

int oldArray[n]={10,20,30,40,50};

Deklarieren Sie ein neues Array, in das Sie Ihren alten Array-Wert kopieren müssen

int newArray[n];

Benutze das

copy_n(oldArray,n,newArray);
Ankit Singh
quelle
1

Da Sie zu C ++ wechseln, wird zunächst empfohlen , den Vektor anstelle des herkömmlichen Arrays zu verwenden . Außerdem ist das Kopieren eines Arrays oder Vektors std::copydie beste Wahl für Sie.

Besuchen Sie diese Seite, um Informationen zur Verwendung der Kopierfunktion zu erhalten: http://en.cppreference.com/w/cpp/algorithm/copy

Beispiel:

std::vector<int> source_vector;
source_vector.push_back(1);
source_vector.push_back(2);
source_vector.push_back(3);
std::vector<int> dest_vector(source_vector.size());
std::copy(source_vector.begin(), source_vector.end(), dest_vector.begin());
Nhan Nguyen Tri Thanh
quelle