Suppose I have a class Widget
with a container data member d_members
, and another container data member d_special_members
containing pointers to distinguished elements of d_members
. The special members are determined in the constructor:
#include <vector>
struct Widget
{
std::vector<int> d_members;
std::vector<int*> d_special_members;
Widget(std::vector<int> members) : d_members(members)
{
for (auto& member : d_members)
if (member % 2 == 0)
d_special_members.push_back(&member);
}
};
What is the best way to implement the copy constructor and operator=()
for such a class?
The
d_special_members
in the copy should point to the copy ofd_members
.Is it necessary to repeat the work that was done in the constructor? I hope this can be avoided.
I would probably like to use the copy-and-swap idiom.
I guess one could use indices instead of pointers, but in my actual use case
d_members
has a type likestd::vector< std::pair<int, int> >
(andd_special_members
is still juststd::vector<int*>
, so it refers to elements of pairs), so this would not be very convenient.Only the existing contents of
d_members
(as given at construction time) are modified by the class; there is never any reallocation (which would invalidate the pointers).It should be possible to construct
Widget
objects withd_members
of arbitrary size at runtime.
Note that the default assignment/copy just copies the pointers:
#include <iostream>
using namespace std;
int main()
{
Widget w1({ 1, 2, 3, 4, 5 });
cout << "First special member of w1: " << *w1.d_special_members[0] << "\n";
Widget w2 = w1;
*w2.d_special_members[0] = 3;
cout << "First special member of w1: " << *w1.d_special_members[0] << "\n";
}
yields
First special member of w1: 2
First special member of w1: 3