Your errors are due to array indexing in C++ being zero-based, but you are using it like arrays are one-based.
for (int i = 1; i < 3; i++) {
temp[i] = friendsList[i];
}
friendsList
points at the first element in a two-element array. This accesses friendsList[1]
, which is okay. (But note that it is the second element in the array, not the first.)
On the next iteration it accesses friendsList[2]
, which would be the third element of the array, but your array only has two elements. This is therefore an out-of-bounds array access, and it causes undefined behavior. In your case, this manifests as an exception by the following sequence of events:
- Your code tries to copy the
friendsList[2]
object (a frnd
), but this is beyond the end of your array allocation. This is undefined behavior and bad, full stop. However, in the interests of explaining why you get this specific exception...
- Copying a
frnd
object uses a default copy constructor, which simply copies each data member of the source object to the target.
- When the compiler tries to copy
friendsList[2].firstName
, you're effectively using some other memory adjacent to your allocation as a std::string
object, when no such object was constructed in that region of memory.
- The
std::string
copy-assignment operator tries to read string-internal data members and gets garbage (uninitialized and/or indeterminate values, the distinction here is pointless because we are already well into UB territory). The first thing it likely tried to do is allocate a char
array using the garbage "string length" value from the non-existent source string object, and if that succeeded then it would try to copy that many characters from a region of memory pointed to by an uninitialized pointer. The odds of coming away from this "copy my garbage data as though it were a string
object" operation without some kind of exception are very, very low.
- Another possible outcome:
&friendsList[2]
could point into a region of memory that hasn't been mapped into your process' address space, triggering an access violation the moment you try to read from it. This would actually be preferable to other things that can happen when you invoke UB.
You can fix this by adjusting the bounds of your loop: (int i = 0; i < 2; i++)
Your second loop, on the other hand, does nothing at all because both i
and size
are 1, so the test i < size
fails.
As pointed out in a comment on your question, you also do not initialize the lastTalked
member of your objects before you attempt to copy them. With some exceptions, reading an uninitialized value causes undefined behavior. Therefore, technically even the first loop iteration when i
is 1 also invokes undefined behavior, but with your specific compiler and architecture this likely manifests as a copy of an indeterminate value.
This can be fixed by adding a default frnd
constructor that initializes the member:
struct frnd
{
frnd() : lastTalked(0) { }
string firstName;
string lastName;
int lastTalked;
};
Other thoughts on your code:
- I understand that this code is an exercise. For production code, however, I need to recommend using
std::vector
instead.
using namespace std;
is bad practice.