0

I'm writing C++ on an Arduino. I've run into a problem trying to copy and array using memcpy.

Character characters[5] = {
    Character("Bob", 40, 20),
    Character("Joe", 30, 10),
    ...
};

I then pass this array into a constructor like so:

Scene scene = Scene(characters, sizeof(characters)/sizeof(Character));

Inside this constructor I attempt to copy the characters using memcpy:

memcpy(this->characters, characters, characters_sz);

This seems to lock up my application. Upon research it appears that memcpy is not the right tool for this job. If I comment that line out the rest of the application continues to freeze.

I can't use vectors because they're not supported on the Arduino, neither is std::copy. Debugging is a pain.

Is there any way to do this?

Edit

The reason why I am copying is because multiple objects will get their own copy of the characters. Each class can modify and destroy them accordingly because their copies. I don't want to have the Scene class responsible for creating the characters, so I'd rather pass them in.

BugHunterUK
  • 8,346
  • 16
  • 65
  • 121
  • 1
    Is `Character` trivially copyable? – imreal Mar 11 '17 at 19:27
  • 4
    You are not using Array. – A.S.H Mar 11 '17 at 19:28
  • 2
    `memcpy()` is a C library function that knows absolutely nothing about C++ classes. – Sam Varshavchik Mar 11 '17 at 19:28
  • 1
    `std::copy()` will do the job. It will probably even decay to `std::memcpy()` for POD types. – Incomputable Mar 11 '17 at 19:43
  • 1
    Why all the hate for someone who's just got involved in C++? What does any of the irrelevant comments have to do with helping someone? I asked because I'm trying to improve my open source [MIDI controller](https://pbs.twimg.com/media/C4fSJExXUAI1lTs.jpg:large). – BugHunterUK Mar 11 '17 at 19:46
  • 1
    @πάνταῥεῖ I think `Arduino` was a rather important tag here (restrictions on the language for example). – Danny_ds Mar 11 '17 at 19:48
  • @Danny No, I don't think it's actually relevant. The restriction about using `std::vector` is already mentioned in the question. – πάντα ῥεῖ Mar 11 '17 at 19:52
  • @A.S.H I wasn't even aware there was `std::array` on the Arduino. By `array` I mean "Array that contains non primitive types". – BugHunterUK Mar 11 '17 at 19:53
  • 1
    @BugHunterUK _"Why all the hate ..."_ What hate?? – πάντα ῥεῖ Mar 11 '17 at 19:53
  • @πάνταῥεῖ regarding your stupid comment on "upon research". I got the information from here http://stackoverflow.com/questions/19439715/using-memcpy-in-c ... "For fundamental types like int, the bitwise copy done by memcpy will work fine. For actual class instances, you need to use std::copy (or copy_n) so that the class's customized assignment operator will be used.". What were you trying to get at exactly? – BugHunterUK Mar 11 '17 at 19:54
  • @BugHunterUK Well, `std::copy()` sounds fine, why are you bothering to use it? – πάντα ῥεῖ Mar 11 '17 at 19:56
  • 2
    @BugHunterUK that's fine, I think you should edit the title because what you are using is called a *"C-style array"* :) – A.S.H Mar 11 '17 at 19:56
  • @πάνταῥεῖ erm ... because `std::copy()` is not available on the Arduino. I already researched that ... something you seem to assume I hadn't done. – BugHunterUK Mar 11 '17 at 19:57

3 Answers3

1

You will have to copy the members individually, or create a copy constructor in the Character class / struct

Danny_ds
  • 11,201
  • 1
  • 24
  • 46
0

It's very unclear what's going on in your code.

  • First of all, you aren't using std::array as your question title suggests, you are using a built-in array. You could concievably use std::array instead, and just use copy constructor of std::array. But that brings us to second question.

  • When you are doing memcpy in the constructor of Scene, what is the actual size of this->characters? It's not a good thing to have a constructor that takes characters_sz dynamically if in fact there is a static limit on how many it can accept.

If I were you and really trying to avoid dynamic allocations and std::vector, I would use std::array for both things, the member of Scene and the temporary variable you are passing, and I would make the constructor a template, so that it can accept arbitrary sized std::array of characters. But, I would put a static assert so that if the size of the passed array is too large, it fails at compile time.

Also assuming you are in C++11 here.


I guess depending on your application, this strategy wouldn't be appropriate. It might be that the size of the arrays really needs to be variable at run-time, but you still don't want to make dynamic allocations. In that case you could have a look at boost::static_vector.

http://www.boost.org/doc/libs/1_62_0/doc/html/container/non_standard_containers.html

boost::static_vector will basically be like a heap-allocated buffer large enough to hold N objects, but it won't default construct N of them for sure, you may have only one or two etc. It will keep track of how many of them are actually alive, and basically act like a stack-allocated std::vector with a capacity limit of N.

Chris Beck
  • 15,614
  • 4
  • 51
  • 87
0

Use std::copy_n:

std::copy_n(characters, num_characters, this->characters);

Note that the order of arguments is different from memcpy and the number is the number of elements, not the size of those elements. You'll also need #include <algorithm> in the top of your source file.

That said, you're probably better off using a std::vector rather than a fixed size array, That way you can just use a simple assignment to copy it, and you can grow and shrink it dynamically.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226