c++11 - c++ vector of shared pointer. If casted outside of vector, will it change the pointer in vector? -


i have base class base , 2 derived classes child_a , child_b. time object my_object instantiated (as shared pointer), don't know it's child_a or child_b. instantiated base. push my_object std::vector of shared pointer of base type. later when know derived class my_object belongs to, use .reset() on my_object cast derived class child_a. question is, my_object in vector cast child_a? if not, how can that? thanks!

edit:

obj_array.push_back(std::shared_ptr<base>(new base()); container.push_back(obj_array[0]]); obj_array[0].reset(child_a()); 

will container[0] cast child_a? how can cast child_a?

edit further clarification of application: guess comment of obj_array can vector of shared_ptr falls application have master container of obj_array> holds object. have several slave containers container1 container2... holds of objects. , have master control of object modifying master container , effect broadcast slave containers. in application, guess need master vector of <shared_ptr<base>>, , have several slave vector of <shared_ptr<shared_ptr<base>>> or <shared_ptr<base>*>.

i've noticed code added question. sharedpointers doesn't that.

sharedpointers "shared" in terms of 'reference counting', not "shared" in terms of "datasharing". "data sharing" in terms done .. pointers. whatever want "share", refer pointer. then, if change it, see update. must change it, not pointer it.

that is, here, want update pointer , want see pointer being updated. therefore, must held pointer pointer.

that is, instead of keeping vector<shared_ptr<base>>, keep vector<shared_pointer<base>*>.

now, when want "globally replace" object new instance, replace shptr<base> held pointer 1 new shptr.

if don't raw pointers, yo umay use vector<shared_pointer<sahred_pointer<base>> , .reset inner while leaving outer untouched. ever got copy of outer see update of inner one.

// obj_array , container vector<shared_ptr<base>*> // or vector<shared_ptr<shared_ptr<base>>>  obj_array.push_back(new std::shared_ptr<base>(new base()); // note 'new' container.push_back(obj_array[0]]);  (*obj_array[0]) .reset(child_a()); // note '*'  obj_array[0] -> reset(child_a()); // or, in short 

edit#2:

after comment "one additional point, obj_array doesn't have vector of pointer pointer. can vector<shared_ptr<base>>. please correct me if i'm wrong":

it depends on want achieve. can keep things in vector anyway - affect scenarious of usage. let me describe abstract setup. have main container somehow holds things. parts of application called a,b,c periodically takes things , performs on them. parts b , c tend internally remember things purpose. assume:

  • case 1: vector holds base* objects,
  • case 2: vector holds shared_ptr<base> objects,
  • case 3: vector holds base**
  • case 4: vector holds shptr<shptr<base>>

of course there more cases possible, let's trim it. now, app running , has objects in main container. modules a,b,c processed something, , modules b , c remembered objects. , application came point needs replace 5th item in main container new bar().

case 1:

vector of base*. bar of course implements base, new bar() directly assignable vector[4]. of course, have decide old element. delete or forget? then, vector[4]=new bar() executed, on reads main vector see new object @ 5th position.

but, that's not end of problem: modules b , c may still know old object. vector's element base* (raw pointer), b/c have copied raw value of pointer-to-old-object, solution explicitely tell b , c perform replace.

thus, case 1 ends following code. split 3 stages: example of initial setup, example of runtime operation, , example of final cleanup.

vector<base*> vector; vector.resize( 10 );  ///// .... later ....  base* olditem = vector[ 4 ]; base* newitem = new bar();  bool iwilldeletetheold = well_somehow_decide();  vector[4] = newitem; moduleb->updateafterreplace(olditem, newitem,  iwilldeletetheold); modulec->updateafterreplace(olditem, newitem,  iwilldeletetheold);  if(iwilldeletetheold)    delete olditem;  ///// .... later ....  for( ... idx ...)     delete vector[idx];  vector.resize(0); 

the modulesb/c read vector items base* , if cache - cache such, base*.

please note piece of code causes write additional function updateafterreplace in every 'module' still remembering old object. , you need orchestrate internal updateafterreplace not ever try delete old object in case going here, or else here double-delete , crash badly. solved here telling them whether iwilldeletetheold. if know it, skip old object deletion phase. however, if decide not delete (iwilldelete=false) still may decide delete on own..

but, that's problem of proper ownership management , not talk here.

case 2:

vector of shared_ptr<base>. bar of course implements base, new bar() directly assignable vector[4] (no change). of course, have decide old element (no change).

(change) but, since held pointer shared_ptr, there's no problem ownership: just overwrite/release pointer, , shptr take care of rest. if uses object, delete it. if still used, keep it.

then, vector[4]=new bar() executed, on reads main vector see new object @ 5th position. (no change)

but, that's not end of problem: modules b , c may still know old object. vector's element sharedptr<base>, b/c have copied shared_ptr-to-old-object, solution explicitely tell b , c perform replace. (no change)

thus, case 2 ends as

vector<shared_ptr<base>> vector; vector.resize( 10 );  ///// .... later ....  sharedptr<base> olditem = vector[4]; sharedptr<base> newitem = new bar();  vector[4].reset( newitem ); // <- line  moduleb->updateafterreplace(olditem, newitem); modulec->updateafterreplace(olditem, newitem);  ///// .... later ....  vector.resize(0); 

the modulesb/c read vector items sharedptr<base> , if cache - cache such, sharedptr<base>. reduction base* convert case case1.

please note how 'decide deletion' , 'object deletion' , 'i-tell-you-that-i-delete-itis gone. benefit ofsharedptr`. however, i still need manually update other caches might still hold old object.

this because line not overwrites shared_ptr, performs 'maybe delete' phase: detaches shared_ptr internal reference counting mechanism , if count drops 0 - deletes object. problem here: detaches. other sharedptr have been copied from shptr in vector[4] forming own refcounting group , still remember old object. did not update contents. collectively dropped refcount=3 refcount=2.

case 3:

vector of base**. bar of course implements base, new bar() not directly assignable vector[4]: vector holds pointer-to-pointer, dereference needed (change). of course, have decide old element (no change). delete or forget? (no change)

then, *vector[4]=new bar() executed, on reads main vector see new object @ 5th position. (no change)

and end of problem. (change)

thus, case 3 ends as

vector<base**> vector; for(int = 0; i<10; ++i)    vector.push( new base* );  ///// .... later ....  base* olditem = * vector[4]; // note dereference base* newitem = new bar();  bool iwilldeletetheold = well_somehow_decide();  * vector[4] = newitem; // note dereference  if(iwilldeletetheold)    delete olditem;  ///// .... later ....  for( ... idx ...) {     delete * vector[idx];  // delete object     delete vector[idx]; // delete pointer }  vector.resize(0); 

the modulesb/c read vector items base** , if cache - cache such, base**. reduction base* convert case case1.

firstly, note vector must initialized pointers. doesn't need done that, may on fly, @ both lines "note dereference" must absolutely sure @ vector[nth] there allocated pointer-to-base* (so, base**, new base*).

as vector's element base**, b/c modules possibly have copied base** - not base*! so, speaking in natural language, modules b/c remember where pointer lies , not where object lies. if change pointer point elsewhere, immediatelly see it, because first @ place-where-pointer-lies, , find there .. new version of pointer.

that way, cascaded update evaporated, , object ownership/deletion simplified, still present. but! also, new fragments appeared: had allocate pointers, have delete them @ point.

case 4:

vector<sharedptr<sharedptr<base>>> vector; for(int = 0; i<10; ++i)    vector.push( new sharedptr<base> );  ///// .... later ....  (* vector[4] ).reset( new bar() ); // note dereference  ///// .... later ....  vector.resize(0); 

the modulesb/c read vector items sharedptr<sharedptr<base>> , if cache - cache such, sharedptr<sharedptr<base>>. reduction base* or sharedptr<base> convert case case1 or case2, respectively.

i hope differences now, not repeat details of happens here.


disclaimer: examples explanatory. none of code tested, none of code "complete". there's example lots of error checking missing. meant show skeleton of mechanisms. may don't compile due typos , etc.

final word #1: of course, may mix pointers , shared pointers freely. instead of shared_ptr<shared_ptr<base>>, can use shared_ptr<base*> or shared_ptr<base>* or base** seen. affects initialization , cleanup. not replace-update problem.

final word #2: please note there the references. if modules b/c captured base* or shared_ptr<base> by reference, there no point in introducing base** or shared_ptr<shared_ptr<base>>.. capture-by-reference introduce same one-more-level-of-indirection required. in fact, reference & internally raw pointer, &-to-base* in fact base**.

final word #3:

i've said it, let me repeat.. core problem shared_ptr 'shared' in terms of reference counting, not data. thus:

shared_ptr<foo> first = new foo(1); shared_ptr<foo> second = first; shared_ptr<foo> third = second;  // first == foo#1   \ // second == foo#1  | refcount = 3 // third == foo#1   /  third.reset( new bar(2) );  // first == foo#1   \ refcount = 2 // second == foo#1  / // third == bar#2   - refcount = 1  second.reset( new asdf(3) );  // first == foo#1   - refcount = 1 // second == asdf#3 - refcount = 1 // third == bar#2   - refcount = 1  first.reset( third );  // first == bar#2                   \ // second == asdf#3 - refcount = 1  | - refcount = 2 // third == bar#2                   / // , foo#1 gets deleted 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -