Vector initialization...

Hi, all, I am stuck on a problem and have tried different approaches, but none of them seem to make sense. Searching the boards hasn't yielded the answer, either - or maybe I am not searching for the right thing...

OK, I have the following defined:

class Test {
public:
char Name[8];
int ID;
int TestNum;
Test();
}

(I also tried this with

typedef struct { ... same stuff basically inside ... } Test;

to no avail)

Then I am trying to do the following:

vector <Test> myTest;

I am not sure how many records I will need to read in before I read them in, so wanted to use a vector...

And it bombs horribly, the moment I try to do a memcpy of a single variable (namely the Name for starters) or even a straight assignment - or using the vector function push_back of a new Test... I guess my thinking is to "Javaish" - I know that there has do be some initialization happening here and that I am missing something obvious but HOW do I initialize that? When I tried to use "new Test();" on a myTest[index], it failed and gave me as an error that I cannot assign it like that.

Help!

Thanks!
Using a class with std::vector requires that the class implements a copy constructor. If no copy constructor is implemented, the default one is used, which is not prepared to copy arrays.

std::vector automatically initializes its elements upon resize using the default constructor or the constructor that takes no parameters.

new is only used in C++ to initialize pointers to [arrays of] dynamic objects, not to construct objects in general. That the main difference between Java/C# and C++. In those two, everything is a pointer (particularly in C#, which is purely OO. Java still has primitive types). In C++, not everything is a pointer.
Thanks, I will try the copy constructor, and see what happens next... :-)
Use code tags. They help people help you because it makes your code easier to read.
Lots of questions in OP, but no code to analyze. memcpy can't be used with non-POD types. What were you trying to memcpy? Post a simple, compilable program that demonstrates the specific problems that you are asking about and someone can take a look at it and provide some advice.
Using a class with std::vector requires that the class implements a copy constructor.


Does it? I was doing some quick searches to confirm and can't find an answer related to this. Most tutorials that I have seen indicate that the copy constructor is needed when you have to manually code deep copies of arrays. You don't have to manually deep copy a vector object correct? It can copy itself. Anyway what I have been reading doesn't say anything about these types of objects such as string and vector that are not POD types but can copy themselves with their own copy constructor and assignment operator.

1
2
3
4
5
6
7
8
9
// Does this struct require a copy constructor and assignment operator?  Or will the 
// defaults for foo subsequently cause the correct copying of any attribute that can copy itself?  
// I always thought that no userdefined operations would be needed to copy or assign these
// Foo class instances.  
struct Foo
{
   std::string name;
   std::vector<std::string> booksRead;
}


You know its funny that I should know the answer but it is so rare that I write a class that requires copying that I don't. The majority of classes that I write in embedded programming don't ever get copied. They are mostly like singletons so I rarely run into this question myself.


1
2
3
4
5
6
7
// definitiely needs a user defined copy constructor and assignment operator.
// if you want deep copies to be made.
struct Foo
{
   char* name;
   char** booksRead;
}
Keep reading.
If no copy constructor is implemented, the default one is used, which is not prepared to copy arrays.
by arrays, you mean arrays allocated using new, correct? If a struct simply has a std::vector as an attribute or an array was not dynamically allocated, I don't think that it needs a custom operator= or copy constructor. I may have just misunderstood what you were saying. It sounded like you were suggesting that the first Foo struct in my example would need to have a custom copy constructor and assignment operator.
I just checked and you're right. Non-heap arrays are correctly copied by the default copy constructor.
Maybe it was that OP was doing the memcpy() wrong?

I'd never suggest a class containing only objects needs a special copy constructor. Besides, OP didn't have such a class.
Thanks for clarifying. Who knows what the OP has because there never was an example posted that demonstrates the problem that occurred in the program. I agree, with you about memcpy. The fact that it was even mentioned by the OP seemed surprising since I can't see the whole program. I'm not sure why memcpy even entered into the equation. memcpy shouldn't be needed at all as far as I can tell.

For instance,
When I tried to use "new Test();" on a myTest[index], it failed and gave me as an error that I cannot assign it like that.


myTest, in the OP, was a vector of Test objects not Test pointers so of course that would fail. In this case, the Test class that I see in the OP doesn't require any user defined copy constructor or assignment operator. It is already copyable with compiler defaults (unless of course it was significantly modified beyond what was posted).
Ok, sorry to be so long in responding, I have limited access to the boards from work...

Anyway, here is the code (sorry it's not in a compilable format):
1
2
3
4
5
6
7
class Test {
     public:
        char   Name[8];
        int      ID;
        int      TestID;
        Test();
}


then, in my main program, I am reading in a file entry that has, for legacy and formatting reasons, be read in one character at a time...

1
2
3
4
while (ch != '\n' || counter == 10) {
    tmpCharBuff[counter] = fgetc(lookupFile);
    counter++;
}  

memcpy (&tmpCharBuff[counter], "\0", 1);

Once checks have been made that this is formatted correctly for the later output that will be required (all of this stuff works), I need to now "stuff" this into the object defined above, namely the Name field of the Test class.

If this were a single object, I could just set it equal to it, but since the above Test class has an unknown amount of instances contained in a vector called MyTest, defined like this:
vector <Test> myTest;

I am not sure how to proceed. Legacy code has similar operations that do not go into a vector object, but a single struct. So I was trying to use something like this:
memcpy(&myTest[chcount].Name, tempBuff, sizeof(tmpBuff));

Which fails miserably (Causing a catastrophic error in the execution, which results in a "This application has encountered an error and has to close."), since this instance of Test has not been initialized. But trying to initialize it how? That is really my question here.

I am sure I am missing something blatantly obvious...

Thanks for all your feedback so far, just bear with me, please, if I take a little longer in responding.

Please post a more complete example. Post a main function along with the declaration of the class that someone like myself could copy and paste into a new project, compile, and execute. Specifically, how are you currently constructing the Test objects and inserting them into the vector? These questions would all be answered by posting a complete example that shows everything that you are doing that results in the crash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// this constructs a vector that is completely empty.
vector <Test> myTest;

// The following line of code will result in undefined behavior.  There are no objects within
// the vector yet.
myTest[0].TestId = 1;

// You have to construct the vector with some number of objects or subsequently insert
// objects.  
vector<Test> myTest(5); // default constructs 5 Test objects.

// Construct empty array.  Then insert some elements.  There are many ways to properly
// insert objects into the vector.  
vector <Test> myTest;

Test testInstance; // default construct an object
myTest.push_back(testInstance); // copies the object and inserts into vector 


First of all, I would avoid the use of memcpy if possible. I assume that you are dealing with null terminated strings so I would use the copying functions available for strings rather than memcpy (strcpy or strncpy). I would also write an interface for the Test class that allows you to pass in a pointer to an array and then allow the member function of the Test class to perform the copying. I don't like the idea of memcpy for direct write to class data members.

By the way, thank you for using code tags in your latest post.
Last edited on
memcpy (&tmpCharBuff[counter], "\0", 1);
This makes no sense. First of all, you're not taking sizeof(char) into consideration (it's usually 1, but still). Second, this is a more contrived form of tmpCharBuff[counter]=0;

memcpy(&myTest[chcount].Name, tempBuff, sizeof(tmpBuff));
Yep. Just as I thought. A screwed up memcpy() call.

memcpy(myTest[chcount].Name, tempBuff, 8*sizeof(char));
I don't know if tempBuff is an array created on the stack or dynamic or passed as a parameter, which is why I didn't use sizeof(tempBuff)*sizeof(*tempBuff).
The problem was that myTest[chcount].Name is already a pointer to the array. When you used the reference operator to get the address of that, you got the address of the pointer itself inside the instance of myTest[chcount] (or something like that. I'm not exactly sure what happens if you get the address of a constant array). The result was that you ended up writing god-knows-where.

EDIT: Ah, sonuva...
Last edited on
Topic archived. No new replies allowed.