I am gradually porting and refactoring C code to C++.
In the original C code, I have constructs like this:
Object* obj = &objects[index];
where objects
is a global Object[]
.
I refactored the code so the array is dynamically allocated and a different object holds the array:
struct Info {
Object* objects;
};
Due to my gradual refactoring, I wrote the following free function:
Object* GetObjects(Info* i) {
return i->objects;
}
Now my question is:
Does the following code behave like I would expect (getting the address of an object in the array)?:
Object* obj = &GetObjects(info)[index];
Am I getting the Address of an object in the array (what I want) here or the address of the pointer or some rvalue and invoke UB?
[]
has higher precedence than &
but does that also count for function calls?
This line:
Object* obj = &GetObjects(info)[index];
Is valid, and should not cause UB by itself.
GetObjects(info)
returns a Object*
(not an rvalue which you were worried about), then it is accessed with operator[]
.
However - the code relies on the Object*
array to stay alive as long as obj
is used. If info
is the owner of it, it will require info
to stay alive as well (assuming it is responsible for its lifetime).
Notes:
Object* obj = &(GetObjects(info)[index]);
struct info
:
struct info
{
Object * GetObjectAtIndex(int index)
{
// TODO: check that the index is valid and return nullptr if not
return &(objects[index]);
}
};
struct info
{
Object & GetObjectAtIndex(int index)
{
// TODO: check that the index is valid, decide what to return if not
return objects[index];
}
};
std::vector
instead of raw C arrays. It also supports a dynamic size as you require. One caveat: std::vector
might need to reallocate when enlarged, and when doing so iterators, references and pointers into it will be invalidated.