add to vector without copying struct data - c++

This is presumable a simple C++ question, but I'm relearning C++ and don't know some of the basics. I have a class that includes a struct with a vector of objects in it, so something like this:
struct my_struct{
Irrelevant_Object object,
vector<tuple> tuple_list;
}
The struct and the tuple (another struct) are predefined by the architecture and given to me in my method; so I can't change them. I want to generate and insert a tuple into the originaly empty tuple_list.
The simple solution is have a method which allocates a new tuple object, fills in the tuple data, then call tuple_list.push_back() and pass in the allocated tuple. But this would require allocating a new tuple only to have the push_back method copy all of the contents of the (large) tuple struct into an already defined memory space of the vector. So I'm paying the expense of an allocation/delete as well as the lesser expense of copying the tuple contents into the vector to do it this way. It seems rather inefficent, and since this method would be in the critical path of the function I would prefer something faster (admitedly I doubt this method would be the bottle-neck, and I know early optimization == bad. However, I'm asking this question more to learn something about C++ syntax then out of a deperate need to actually do this in my code).
So my question is, is there a quicker way to fill the contents of my tuple list without allocating and copying a tuple? If this was an array I could make the array as large as I want, then past a reference to tuple_list[0] to the function that creates the tuple. That way the funciton could fill the empty contents of the already allocated tuple within the array without allocating a new one or copying from one tuple to another. I tried to do that with the vector out of curiousity and ended up with a seg fault when my itterator pointed to 0x0, so I assume that syntax doesn't work for vectors. So is there a quick way of doing this assignment?
Since this is a question as much to learn the language as for actual use feel free to throw in any other tangentally relevant stuff you think are interesting, I'm looking to learn.
Thanks.

In C++11, you can use std::vector::emplace_back, which constructs the new object in-place, therefore there is no copying when you use this method.
By using this method, you could do this:
my_struct some_struct;
some_struct.tuple_list.emplace_back(1, 5, "bleh");
Assuming your tuple object contains this constructor:
tuple::tuple(int, int, const std::string&)
Edit: You can also use move semantics to store a pre-allocated tuple:
my_struct some_struct;
tuple a_tuple;
/* modify a_tuple, initialize it, whatever... */
some_struct.push_back(std::move(a_tuple)); // move it into your vector
Or use a reference to the tuple after it has been stored in the vector:
my_struct some_struct;
some_struct.tuple_list.emplace_back(1, 5, "bleh");
// store a reference to the last element(the one we've just inserted)
tuple &some_tuple = some_struct.tuple_list.back();
some_tuple.foo();
On all of the above solutions you're creating only one tuple while also avoiding copying.

Related

How do I copy arrays that contain non primitive types?

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.
You will have to copy the members individually, or create a copy constructor in the Character class / struct
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.
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.

std vector construct element once [duplicate]

This question already has answers here:
How can I create objects while adding them into a vector?
(5 answers)
Closed 9 years ago.
This is a pretty straight forward question.
Is there a way to have a vector and initialize an element without constructing and then copying it?
class BigType
{
// has a costly copy constructor
};
int main(void)
{
using std::vector;
vector<BigType> bigTypeVec;
bigTypeVec.push_back(BigType(/*constructor from parameters*/));
// This constructs a temp object, and then copies it to the new element.
}
Of course there are all sorts of work-a-rounds involving vectors of pointers, or instead of using a constructor, initialize an element's components with set functions, however I was wondering if there were a way to do it so that it can call the constructor on the element it allocates during push_back.
Edit: This question was marked as a duplicate, however I had viewed that page and the answers to his question hadn't answered mine. I want to know how to set the value of the element by constructing it once, rather then copy constructing a temporary object into the element. Emplace was a good way to do this.
You could use std::vector<...>::emplace() or, if you want to append the object, std::vector<...>::emplace_back(), to construct the object in place. If you have to use C++03 this member function isn't available. As an approximation you could push_back() and empty object and then swap() your BigType into the corresponding location, assuming you could construct a small empty object.
Note that std::vector<...> isn't necessarily the best data structure if you have huge objects: if the reserved spaces runs out, the vector need to shuffle the objects around to make new space. You might want to use std::deque<...> instead, as it won't leave its objects put (unless you insert into the middle) while having similar access characteristics as std::vector<...>.
with C++11, yes.
bigTypeVec.emplace_back(BigType());
Here's some more info:
http://en.cppreference.com/w/cpp/container/vector/emplace_back
"Is there a way to have a vector and initialize an element without constructing and then copying it?"
Yes.
Consider placement new as a mechanism to side-step the use of a copy assignment and it's use of a temporary.
"Is there a way to have a vector..."
A vector can be built with elements created with the default constructor.
I believe it is possible to define BigType so that no element initialization is required during the bigTypeVec construction. In this way, declaring the vector (or even a simple array) will trigger no element constructor work. Consider these:
vector<BigType> bigTypeVec;
or
BigType bigTypeVec[MAX_BigTypeVecSize];
Note that the array requires BigType to provide a default constructor (or you to provide a big bunch of curly brace array initialzation).
However, I can imagine that you might find value for each BigType element to have an indication that it is or is not initialized.
" and initialize an element without constructing [a temp] and then copying it [, the temp, to the vector]?"
Placement new can then be used to construct the object in place. By passing the address of the desired bigTypeVec element you wish to initialize to the placement new, all the element constructor work will occur where (in memory) you want it. Consider something like:
vector<BigType> bigTypeVec;
BigType* pBT = 0;
pBT = new (&bigTypeVec[0] BigType(<param>); // placement new
pBT = new (&bigTypeVec[1] BigType(<param>);
...
pBT = new (&bigTypeVec[n] BigType(<param>);
Note the discard of pBT. Pointer is not used.
*"I was wondering if there were a way to do it so that it can call the constructor on the element it allocates during push_back."*
At this point, all that remains is to create the simplest class possible that inherits from std::vector() and re-impliments "push back", or perhaps a new method that supports your needs. These methods would seek the vector element that push-back would have found, and use the placement new similar to above.
Are you sure about this?
"This constructs a temp object, and then copies it to the new element."
As far as I know, it will directly create an object at the memory location. Return value optimization. Temporary will not be created.
Am I wrong?

enter values in structure using vectors

I have created this structure:
struct xlsmain {
vector<sub_parts> sb;
string name;
}
struct sub_parts {
vector<pio_parts> pio;
string name_pio;
string direction;
string partition;
}
struct pio_parts {
string pio_name;
vector<report_specs> report;
}
struct report_specs {
string name;
vector<string> value;
}
struct xlsmain* interface = new xlsmain[100];
The nesting is necessary because every element is related in a heirarchial manner. The problem I am facing right now is how to enter values in this structure.
EDIT: I don't like using push_back() because every time I'll have to declare a separate structure. So for instance if I want to add a sub part to xlsmain, I have to declare a variable:
sub_parts sb1;
Then I have to feed values into this structure until it is finished, when I can use:
interface[i].sb.push_back(sb1);
Further, if nesting is involved then a number of structures like sb1 will also have to be created. This leads to having to create a large number of variables just to enter even a single value in my structure.
An option would be to use a std::map instead of the vector, then you can do something like this
xmlsmain["some element"].sb["some other"].direction = "up";
In this way, elements "some element" and "some other" are automatically created.
Before the edit, your concern that push_back() was "too complex" wasn't clear. (It sounded like perhaps even you didn't like the name of the method...or something strange like that?)
I'll try to get to addressing the new issue raised. But I will reiterate that although you are using the standard library string and vector classes, your structures are not themselves getting the advantages of C++!
You don't have constructors, destructors, or methods. Those are the foundations of letting data objects "come alive" with "magic" behavior that lets clients of these classes write simpler, more abstract code. This is helpful even if your only "client" is just more of your own code!
Let's say before you had code like:
pio_parts pp;
pp.pio_name = "this string will be stored in the name";
pp.report.push_back(someReport);
pp.report.push_back(anotherReport);
If you add a constructor and a method to your structure, like this:
struct pio_parts {
string pio_name;
vector<report_specs> report;
pio_parts(string newName) {
pio_name = newName;
}
void addReport(report_specs newSpecs) {
report.push_back(newSpecs);
}
};
Then the code above gets nicer:
pio_parts pp ("this string will be stored in the name");
pp.addReport(someReport);
pp.addReport(anotherReport);
Though really, you've not done much than save yourself from having to know the name of the data member in pio_parts to add to. Now you remember a method name instead. You save a little typing, but push_back() was about as good.
HOWEVER if there were more related operations you need to do inside of addReport() than just add to the vector, you now have a place to put all that code. That way the user of your class can not worry about whatever bookkeeping is necessary to add a report...they just ask that it be done! Also, since there's no call to push_back() it's no longer necessary for whoever is calling addReport() to know that the list is being stored in a vector.
I've deliberately not even bothered to try and scratch deeper into the specifics of references, copy-construction, smart pointers, member initialization syntax, or even class vs struct. It's too deep a language. Take a time out ASAP and carefully read this short paper by Bjarne Stroustrup that lays out that clear contrast in methodology:
Learning Standard C++ as a New Language
Now I'll try to get on to your other concern. First of all, you do not have to create a named instance of a variable in C++ to pass it to a function. You can rewrite:
sub_parts sb1;
interface[i].sb.push_back(sb1);
...as instead:
interface[i].sb.push_back(sub_parts ());
Not particularly useful in this case, as the object is constructed empty...so you just pushed something useless. But if your constructor took parameters that filled the object, it would be fine. You can even build up arrays like this:
How can I initialize an array of objects whose constructor require two or more arguments?
But if your constructor takes a hardcoded list (as yours seem to), then there's been a bit of a fly in the ointment. While C++ can initialize ordinary arrays with values you code in directly, passing the ordinary array loses its length information. A vector would be better, but initializing them with hardcoded values is clunky:
What is the easiest way to initialize a std::vector with hardcoded elements?
You can see that people had pretty much the same complaint you did about having to write:
std::vector<int> ints;
ints.push_back(10);
ints.push_back(20);
ints.push_back(30);
That post lists some of the workarounds, but bleeding edge compilers (probably not what you're using) support:
std::vector<int> ints = {10, 20, 30};
Once you have those, it makes it extremely easy to do your "nested" style constructions.
As a final note: you seemed on an earlier comment to concretely ask about raw arrays vs vectors. For your interface you almost certainly want a vector. Here's a pitfall: using new xlsmain[100] on a raw array requires to remember to do a delete[] interface (and not just a regular delete interface):
delete vs delete[] operators in C++
Bear in mind there is also no realloc in C++ anyway. So if that's why you were dynamically allocating it, forget about that idea.
You can save yourself from trouble like this by just making interface a vector. You will be able to resize it if you ever need to, and also avoid hard-coding a so-called "Magic Number" into your program.

c++ vector construct with given memory

I'd like to use a std::vector to control a given piece of memory. First of all I'm pretty sure this isn't good practice, but curiosity has the better of me and I'd like to know how to do this anyway.
The problem I have is a method like this:
vector<float> getRow(unsigned long rowIndex)
{
float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control
vector<float> returnValue(row, row+_m->cols()); // construct a new vec from this data
delete [] row; // delete the original memory
return returnValue; // return the new vector
}
_m is a DLL interface class which returns an array of float which is the callers responsibility to delete. So I'd like to wrap this in a vector and return that to the user.... but this implementation allocates new memory for the vector, copies it, and then deletes the returned memory, then returns the vector.
What I'd like to do is to straight up tell the new vector that it has full control over this block of memory so when it gets deleted that memory gets cleaned up.
UPDATE: The original motivation for this (memory returned from a DLL) has been fairly firmly squashed by a number of responders :) However, I'd love to know the answer to the question anyway... Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?
The obvious answer is to use a custom allocator, however you might find that is really quite a heavyweight solution for what you need. If you want to do it, the simplest way is to take the allocator defined (as the default scond template argument to vector<>) by the implementation, copy that and make it work as required.
Another solution might be to define a template specialisation of vector, define as much of the interface as you actually need and implement the memory customisation.
Finally, how about defining your own container with a conforming STL interface, defining random access iterators etc. This might be quite easy given that underlying array will map nicely to vector<>, and pointers into it will map to iterators.
Comment on UPDATE: "Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?"
Surely the simple answer here is "No". Provided you want the result to be a vector<>, then it has to support growing as required, such as through the reserve() method, and that will not be possible for a given fixed allocation. So the real question is really: what exactly do you want to achieve? Something that can be used like vector<>, or something that really does have to in some sense be a vector, and if so, what is that sense?
Vector's default allocator doesn't provide this type of access to its internals. You could do it with your own allocator (vector's second template parameter), but that would change the type of the vector.
It would be much easier if you could write directly into the vector:
vector<float> getRow(unsigned long rowIndex) {
vector<float> row (_m->cols());
_m->getRow(rowIndex, &row[0]); // writes _m->cols() values into &row[0]
return row;
}
Note that &row[0] is a float* and it is guaranteed for vector to store items contiguously.
The most important thing to know here is that different DLL/Modules have different Heaps. This means that any memory that is allocated from a DLL needs to be deleted from that DLL (it's not just a matter of compiler version or delete vs delete[] or whatever). DO NOT PASS MEMORY MANAGEMENT RESPONSIBILITY ACROSS A DLL BOUNDARY. This includes creating a std::vector in a dll and returning it. But it also includes passing a std::vector to the DLL to be filled by the DLL; such an operation is unsafe since you don't know for sure that the std::vector will not try a resize of some kind while it is being filled with values.
There are two options:
Define your own allocator for the std::vector class that uses an allocation function that is guaranteed to reside in the DLL/Module from which the vector was created. This can easily be done with dynamic binding (that is, make the allocator class call some virtual function). Since dynamic binding will look-up in the vtable for the function call, it is guaranteed that it will fall in the code from the DLL/Module that originally created it.
Don't pass the vector object to or from the DLL. You can use, for example, a function getRowBegin() and getRowEnd() that return iterators (i.e. pointers) in the row array (if it is contiguous), and let the user std::copy that into its own, local std::vector object. You could also do it the other way around, pass the iterators begin() and end() to a function like fillRowInto(begin, end).
This problem is very real, although many people neglect it without knowing. Don't underestimate it. I have personally suffered silent bugs related to this issue and it wasn't pretty! It took me months to resolve it.
I have checked in the source code, and boost::shared_ptr and boost::shared_array use dynamic binding (first option above) to deal with this.. however, they are not guaranteed to be binary compatible. Still, this could be a slightly better option (usually binary compatibility is a much lesser problem than memory management across modules).
Your best bet is probably a std::vector<shared_ptr<MatrixCelType>>.
Lots more details in this thread.
If you're trying to change where/how the vector allocates/reallocates/deallocates memory, the allocator template parameter of the vector class is what you're looking for.
If you're simply trying to avoid the overhead of construction, copy construction, assignment, and destruction, then allow the user to instantiate the vector, then pass it to your function by reference. The user is then responsible for construction and destruction.
It sounds like what you're looking for is a form of smart pointer. One that deletes what it points to when it's destroyed. Look into the Boost libraries or roll your own in that case.
The Boost.SmartPtr library contains a whole lot of interesting classes, some of which are dedicated to handle arrays.
For example, behold scoped_array:
int main(int argc, char* argv[])
{
boost::scoped_array<float> array(_m->getRow(atoi(argv[1])));
return 0;
}
The issue, of course, is that scoped_array cannot be copied, so if you really want a std::vector<float>, #Fred Nurk's is probably the best you can get.
In the ideal case you'd want the equivalent to unique_ptr but in array form, however I don't think it's part of the standard.

Avoid making copies with vectors of vectors

I want to be able to have a vector of vectors of some type such as:
vector<vector<MyStruct> > vecOfVec;
I then create a vector of MyStruct, and populate it.
vector<MyStruct> someStructs;
// Populate it with data
Then finally add someStructs to vecOfVec;
vecOfVec.push_back(someStructs);
What I want to do is avoid having the copy constructor calls when pushing the vector. I know this can be accomplished by using a vector of pointers, but I'd like to avoid that if possible.
One strategy I've thought of seems to work, but I don't know if I'm over-engineering this problem.
// Push back an empty vector
vecOfVec.push_back(vector<MyStruct>());
// Swap the empty with the filled vector (constant time)
vecOfVec.back().swap(someStructs);
This seems like it would add my vector without having to do any copies, but this seems like something a compiler would already be doing during optimization.
Do you think this is a good strategy?
Edit: Simplified my swap statement due to some suggestions.
The swap trick is as good as it gets with C++03. In C++0x, you'll be able to use the vector's move constructor via std::move to achieve the same thing in a more obvious way.
Another option is to not create a separate vector<MyStruct>, but instead have the code that creates it accept it a a vector<MyStruct>& argument, and operate on it. Then, you add a new empty element to your outer vector<vector<MyStruct>>, and pass a reference to the code that will fill it.
I know this can be accomplished by
using a vector of pointers, but I'd
like to avoid that if possible.
Why?
That would be the most intuitive/readable/maintainable solution and would be much better than any weird hacks anyone comes up with (such as the swap you show).
Tim,
There's a common pattern to solve this. This is called smart pointers, and the best one to use is boost::shared_ptr.
Then, never pass vector by value or store it. Instead, store boost::shared_ptr >. You don't need to care about allocations/deallocations (when the containing vector is destroyed, so will be the others, just as in your code), and you can access the inner members almost the same way. The copy is, however, avoided by means of the smart pointer object's reference counting mechanism.
Let me show you how.
using boost::shared_ptr;
vector<shared_ptr<vector<MyStruct> > vecOfVecs;
shared_ptr<vector<MyStruct> > someStructs(new vector<MyStruct>);
// fill in the vector MyStructs
MyStructs->push_back(some struct.... as you usually do).
//...
vecOfVecs.push_back(someStructs); // Look! No copy!
If you do not already use boost::shared_ptr, I recommend downloading it from boost.org rather than implementing your own. It is really irreplaceable tool, soon to be in the C++ standard library.
You can either do something like vect.push_back(vector<MyStruct>()); and do vect.back().push_back(MyStruct()); or use smart pointers and have a vector of smart pointers to vector<MyStruct>
I think the swap idea is already fine, but can be written much easier:
vecOfVec.push_back(vector<MyStruct>());
vecOfVec.back().swap(someStructs);