C / C ++で配列をコピーする機能はありますか?


92

私はC / C ++を学ぶJavaプログラマーです。したがって、JavaにはSystem.arraycopy()のような関数があることがわかります。配列をコピーします。配列をコピーする関数がCまたはC ++にあるかどうか疑問に思いました。forループ、ポインターなどを使用して配列をコピーする実装を見つけることしかできませんでした。配列をコピーするために使用できる関数はありますか?


7
man memmoveおよびman memcpy
Tim Cooper

28
使用しないでくださいmemcpy、使用してくださいstd::copy。タイプに意味のあるコピーコンストラクターがある場合memcpy、間違ったことをします。
Ed S.

10
あなたは実際にCとC ++を同時に学ぼうとしていますか?それらは非常に異なる言語です。
フェルッチオ2013

1
さて、私はCを少し学びましたが、最近C ++を学び始めました。オンラインリソースから読んだところによると、C ++はC言語に多くの追加機能を備えた単なる言語だと思いました。
JL

6
これまで誰も言及していないので、これを言っています。C++では、ほとんどすべての場合にstd :: vectorを使用する必要があります。他のコンテナも役立つ場合がありますが、ほとんどの場合、std :: vectorが最適なオプションです。C ++では生の配列を使用せず、必要な場合を除いてstd :: arrayを避けてください。
Skalli 2013

回答:


79

C ++ 11以降、std::array:を使用して配列を直接コピーできます。

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

std :: arrayに関するドキュメントは次のとおりです


@XAleXOwnZX:コピーの割り当てをサポートする他のタイプと同じです。B = A
swalog 2015年

2
関数はAのメモリアドレスをBにコピーすることだと思います。Bのメモリアドレスを変更せずにAのアイテム値をBにコピーしようとすると。どうやってやるの?
アーロンリー

@Aaron_Lee:テストしたばかりで、要素を別のメモリ位置の配列に真にコピーします。配列クラスには、明らかに、代入演算子に対して独自のオーバーロードがあります。
DaveRove19年

5
皆さんは、これらの2行のコードに代入演算子が表示されていないことに気づいていますよね?これは、表記が代入演算子のように見えても呼び出されるコピーコンストラクターです。
アルビーノコル

141

あなたがC ++ソリューションを求めたので...

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

2
erreur:「begin」は「std」のメンバーではありません
–David天宇ウォン2014

23
@David天宇ウォン:古いコンパイラを使用しているか、ヘッダーを含めていません。あります<iterator>
Ed S.

9
多分あなたはあなたが必要とするものを含むと言うべきです。コピーは入ってい<algorithm>ますか?
ジェリージェレマイア2016

17
std :: beginが<iterator>にあることを説明する必要がある場合、つまり、std :: beginがどのヘッダーにあるかを調べ始めていないため、同じようにstd :: copyをグーグルで検索する可能性は低いためです。理由。コメントでしか答えられないことを誰も尋ねる必要がないなら、それはより良い答えになります。たぶん私はあなたにそれをするように促すのではなく、答えを編集するべきでした。
ジェリージェレマイア2016

3
begin(src)をsrcに、end(src)をsrc + arr_sizeに変更できます
Calvin

83

他の人が述べたように、Cではを使用しますmemcpy。ただし、これは生のメモリコピーを実行するため、データ構造にそれ自体または相互へのポインタがある場合でも、コピー内のポインタは元のオブジェクトを指していることに注意してください。

C ++ではmemcpy、配列メンバーがPOD(つまり、基本的にCでも変更せずに使用できたタイプ)の場合にも使用できますが、通常は許可memcpyされません。他の人が述べたように、使用する関数はstd::copyです。

そうは言っても、C ++では、生の配列を使用することはめったにありません。代わりに、標準コンテナの1つを使用する必要があります(std::vector組み込み配列に最も近く、Java配列に最も近いと思います—実際にはプレーンC ++配列よりも近いですがstd::dequestd::list場合によってはより適切な場合もあります)または、std::array組み込み配列に非常に近いが、他のC ++タイプと同様の値セマンティクスを持つC ++ 11を使用する場合。ここで説明したすべてのタイプは、割り当てまたはコピー作成によってコピーできます。さらに、イテレータ構文を使用して、opneから別のopneに(さらには組み込み配列から)「クロスコピー」することができます。

これにより、可能性の概要がわかります(関連するすべてのヘッダーが含まれていると思います)。

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

1
memcpyの例は間違っています。ソースと宛先が入れ替わります。
AT -学生

1
実際、このmemcpy例の間違いはそれだけではありません。サイズも間違っていました。修正しました、ありがとうございます。
celtschk 2015

stdの名前空間を使用するのではなく、常にstdを記述しているのはなぜですか?
ブラック

memcpy(b、a、sizeof a);を実行できません。あまりにも?
rodi 2015年

Java配列は、サイズが固定されているためstd:array、に似std::vectorています。
Bart van Heukelom 2016年

17

あなたは使用することができmemcpy()

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

memcpy()num指す場所から、が指すsourceメモリブロックにバイトの値を直接コピーしますdestination

destinationsourceが重なっている場合は、を使用できますmemmove()

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

memmove()num指す場所から。がsource指すメモリブロックにバイトの値をコピーしますdestination。コピーは、中間バッファが使用されているかのように行われ、宛先とソースが重複する可能性があります。


3
ここで-1にする必要があります。OPは特にC ++ソリューションを求めており、この回答はmemcpy、バイトのコピーが不十分であるなど、間違っている状況については何も述べていません。
Ed S.

2
@EdS。お気づきの方もいらっしゃると思いますが、OPは現在CまたはC ++ソリューションを求めています。
自閉症

4
私が答えたとき、OPはC / C ++ソリューションを求めていましたが、個人的には「C / C ++」は両方の言語を侮辱していると思います。:)
Deepu 2013

十分に公平で、私はそれが変化していることに気づいていませんでした。多分それは以前にそれを言った、そして私はそれを逃した。-1が削除されました。
Ed S.

2
@EdS 2分だと思いましたが、この回答が投稿された時点では、質問はCとC ++の両方に言及していました。私が間違っていて、ある時点で質問にC ++しか書かれていなかったとしても、反対票は正当化されませんでした。
ジムバルター2013

16

memcpyC、std::copyC ++で使用します。


小さな配列の場合、関数呼び出しのオーバーヘッドは発生しないと思います(memcpyコンパイラ組み込み関数である必要があります)?
wcochran 2016

@Mehrdad私は他に言いませんでした。コメントするだけです。そして、私もそれを否定しませんでした。
MD XF 2016

12

Ed S.の答えが好きですが、これは固定サイズの配列でのみ機能し、配列がポインターとして定義されている場合は機能しません。

したがって、配列がポインターとして定義されているC ++ソリューションは次のとおりです。

#include<algorithm>
...
const int bufferSize = 10;
char* origArray, newArray;
std::copy(origArray, origArray + bufferSize, newArray);

buffersize1で差し引く必要はありません。

  1. [first、last)の範囲内のすべての要素を、最初から最後までコピーします-1

参照:https//en.cppreference.com/w/cpp/algorithm/copy



3

C ++ 11ではCopy()、stdコンテナで機能するものを使用できます

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

std::endパフォーマンス上の理由から、ループから抜け出すことをお勧めします(c1はループ中にイテレーターを変更または無効化しないため、終了を再計算する必要はありません)。
celtschk 2016

3

ここでは、C言語とC ++言語の配列に対処する2つの方法を示します。memcpycopyはどちらもC ++で使用できますが、copyはCでは使用できません。Cで配列をコピーしようとしている場合は、memcpyを使用する必要があります。

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

4
using namespace std;悪い習慣です。絶対に使用しないでください。cplusplus.comの代わりに、cppreference.comを使用してください。これには、標準のはるかに優れた最新のドキュメントが含まれています。stdio.hC ++での同等のものはcstdio、代わりにそれを使用することです。さらに、コードはかなり非慣用的なC ++です。CとC ++の別々のソリューションを紹介した方が、はるかに明確になると思います。
タンブル2017

3

コードに標準ライブラリを含めるだけです。

#include<algorithm>

配列サイズは次のように示されます n

古いアレイ

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

古い配列値をコピーする必要がある新しい配列を宣言します

int newArray[n];

これを使って

copy_n(oldArray,n,newArray);

1

まず、C ++に切り替えるため、従来の配列の代わりにベクトルを使用することをお勧めします。その上、配列またはベクトルをコピーすることはあなたにとって最良の選択です。std::copy

コピー機能の使用方法については、次のページにアクセスしてください:http//en.cppreference.com/w/cpp/algorithm/copy

例:

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());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.