Sunday, 15 May 2011

c++ Implicit copy of *this with std::list -



c++ Implicit copy of *this with std::list -

for project, have list of objects, (in illustration code, garden). each garden contains single plant, has reference garden it's in. works when making single garden, when create std::list of garden objects, re-create created somewhere don't know, , have no thought how prepare it. objects following:

struct garden; //forward declaration struct plant { plant(garden & mygarden) : thegarden(mygarden) { }; //constructor garden & thegarden; //reference garden plant in }; struct garden { garden(int size) : theplant(*this), size(size) { }; //constructor plant theplant; //plant contained in garden int size; //size of garden };

so far good. now, can create garden stand-alone, or set 1 in list. expected behaviour if alter 'size' variable, gets changed everywhere, in thegarden. however, in list, gets changed in 'original' garden, not in reference thegarden

int main() { //works garden onegarden(1); std::cout << "expected: 1 1, result: " << onegarden.size << " " << onegarden.theplant.thegarden.size << std::endl; onegarden.size = 2; std::cout << "expected: 2 2, result: " << onegarden.size << " " << onegarden.theplant.thegarden.size << std::endl; //does not work! std::list<garden> gardenlist; gardenlist.push_back(garden(1)); std::cout << "expected: 1 1, result: " << gardenlist.front().size << " " << gardenlist.front().theplant.thegarden.size << std::endl; gardenlist.front().size = 2; std::cout << "expected: 2 2, result: " << gardenlist.front().size << " " << gardenlist.front().theplant.thegarden.size << std::endl; homecoming 0; }

the final output following:

expected: 1 1, result: 1 1 expected: 2 2, result: 2 2 expected: 1 1, result: 1 1 expected: 2 2, result: 2 1

standard containers own elements contain. means copies made of each element when insert them.

when garden copied, default re-create constructor used and, in turn, plant fellow member default-copied. however, means new plant contains reference old garden.

in case, old garden temporary in gardenlist.push_back(garden(1)) not not right garden, it's garden doesn't exist more. in short, reading size through dangling reference (which has undefined behaviour) , getting [un?]fortunate plenty see old value behind it.

you should write re-create constructor garden copies plant in every way except new plant should have reference new garden, instead of copying old reference.

the re-create , entire issue stems can avoided using new c++11 features:

gardenlist.emplace_back(1);

now, the garden in list created in-place, , no re-create performed.

however, should still prepare underlying design problem garden, if work around problem in way.

c++ list oop reference std

No comments:

Post a Comment