c++ vector 사용시 vector 안에 모든걸 memcpy 로 한번에 복사 가능한가요?

kknd345의 이미지

class Point;
char tmp[4096];

vector vPoint;

해서

vPoint에 push_back을 이용해서 Point를 n개를 집어 넣었습니다.

그 뒤에 vPoint 내용을 char 배열에 복사해야 되는 경우가 생겨서

memcpy( tmp, vPoint, sizeof(Point)*n );

위 처럼했는데 결과값이 이상합니다.

저런식으로 하면 안되나요? for문 돌려서 at()이나 pop_back()이용해서 복사하는 법은 알겠는데

memcpy로 한번에 바로 할수 있는 방법은 없나요?

혹시 바로 안되면 왜 안되는지 좀 가르쳐 주세요 부탁드리겠습니다.

doldori의 이미지

memcpy( tmp, &vPoint[0], sizeof(Point)*n );

krisna의 이미지

저 방법이 표준에서 보장해 주는 방법인가요?
다시 말해서 std::vector에 한해서 저렇게 사용해도 괜찮은 건지 궁금합니다.
std::string::c_str() 같은 함수처럼 사용할 수 있는 것인지요?

thyoo의 이미지

C++ 표준은
 std::vector<class T, class Allocator=allocator<T> >
Interface와 그 동작 요구사항만을 기술합니다.
그러므로 vector의 내부 데이터 구조가 array냐 아니냐는
전적으로 구현에 의존합니다.
위의 코드는 Portable하지 않을 수도 있읍니다.

하지만 표준의 요구사항을 만족할 만한
데이터 구조로서는 array보다 단순하고 효율적인 구조가 없지요.
(array말고 다른 data structure로 구현한 걸 여태 본 적이 없읍니다)
Stroustrup도 TCPL에서 one-dimensional array of T 라고
하고 있읍니다.
vector의 의도된 바는 extended array (range checked, dynamically growing)이므로 위에서 처럼 사용해도 무방하리라 봅니다.
(다른 사람이 보면 불안하겠지요. 저라면 야단치겠읍니다.)
다만, 내부에서 reallocation이 일어날 수도 있으므로
그 포인터를 기억해 두면 안됩니다.

위에서 Point가 단순 structure가 아니라면
Shallow Copy가 발생할 수 있읍니다.
C++식으로 Copy Ctor를 만들고 루프 돌리거나
 std::copy 쓰세요.

그리고, char buffer에 담는 것으로 봐서는
file이나 socket에 쓰려고하는 것 같은데,
Structure Alignment도 문제될 수 있으므로,
더더군다나 루프를 돌려야겠읍니다.
http://www.parashift.com/c++-faq-lite/serialization.html
___________________________________
Less is More (Robert Browning)

___________________________________
Less is More (Robert Browning)

doldori의 이미지

thyoo님께서 잘 설명해 주셨습니다.
부연하면 memcpy()처럼 쓰인 코드가 작동하는 이유는 vector의 모든 원소가
배열과 마찬가지로 연속으로 배치된다는 가정에 의한 것입니다. 현재 표준에는
이것이 명시되어 있지 않으므로 엄밀히 말하면 표준에 의해 보장받지 못합니다만,
vector라는 컨테이너가 배열을 모델로 한 것이라는 점도 사실입니다.

현재 진행중인 표준 개정 작업에는 이러한 사항을 명시하도록 수정하고 있습니다.

Quote:

23.2.4/1

(...) The elements of a vector are stored contiguously,
meaning that if v is a vector<T, Allocator> where T is some type other than bool,
then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().


doldori의 이미지

잘못된 부분이 있어 정정합니다.
위에서 인용한 문구는 이미 2003년 개정안에서 적용되었습니다.
즉 memcpy()처럼 쓰이는 용법은 현재 표준에 의해 보장받는 것입니다.
그러나 thyoo님이 지적하신 문제점에 대해서는 충분히 이해하고
주의해서 써야겠습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.