Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #67046 > unrolled thread
| Started by | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| First post | 2019-07-16 00:00 +0200 |
| Last post | 2019-07-17 07:36 +0000 |
| Articles | 18 — 6 participants |
Back to article view | Back to comp.lang.c++
[niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 00:00 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Öö Tiib <ootiib@hot.ee> - 2019-07-15 15:40 -0700
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 01:18 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-07-15 21:12 -0400
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 14:28 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-07-16 09:47 -0400
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 17:16 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-07-16 10:30 -0700
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 19:44 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Rosario19 <Ros@invalid.invalid> - 2019-07-23 09:28 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Öö Tiib <ootiib@hot.ee> - 2019-07-15 20:22 -0700
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 14:37 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Öö Tiib <ootiib@hot.ee> - 2019-07-17 01:41 -0700
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Paavo Helde <myfirstname@osa.pri.ee> - 2019-07-16 15:04 +0300
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Soviet_Mario <SovietMario@CCCP.MIR> - 2019-07-16 14:42 +0200
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Paavo Helde <myfirstname@osa.pri.ee> - 2019-07-16 16:15 +0300
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-07-16 10:07 -0400
Re: [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? Juha Nieminen <nospam@thanks.invalid> - 2019-07-17 07:36 +0000
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 00:00 +0200 |
| Subject | [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? |
| Message-ID | <qgit2g$qd3$1@dont-email.me> |
I've been a long time far from C++ and I realize I have forgotten most, and moreover don't understand "modern" C++ .... anyway When in a function (member or not is irrelevant) I build an aggregate object (class / struct, possibly nested with other), and this aggregate has a DEFAULT public constructor which does not resort to new or new [], but then the said former function invokes some class methods that DO some dynamic allocation, and then the function returns passing outside a copy by-value of the built object to the caller, placed "partially" on the stack, the final copy will be shallow or deep ? With shallow I mean : every automatic member not requiring new or new [], with deep copy I mean exact copy (or even the temporary itself ...). another maybe relevant detail is it relevant whether the COPY constructor is defined or the default one ? How behaves a default generated copy constructor ? Does it perform also new/ new [] operations ? Is it really the COPY constructor that is called on such a situation (returning a complex type by-value instead of by-pointer) ? or a COPY constructor is given, which does not do deep copy, but just "automatic" data is replicated. In case I defined a COPY constructor making dynamic allocation, is it : 1) required, 2) optional or 3) deprecated and possibly dangerous define also an explicit DESTRUCTOR making cleanups ? TY -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-07-15 15:40 -0700 |
| Message-ID | <768dccb2-7087-4abc-a430-1a7ee63e00b1@googlegroups.com> |
| In reply to | #67046 |
On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: > I've been a long time far from C++ and I realize I have > forgotten most, and moreover don't understand "modern" C++ > .... anyway > > When in a function (member or not is irrelevant) I build an > aggregate object (class / struct, possibly nested with > other), and this aggregate has a DEFAULT public constructor > which does not resort to new or new [], but then the said > former function invokes some class methods that DO some > dynamic allocation, and then the function returns passing > outside a copy by-value of the built object to the caller, > placed "partially" on the stack, the final copy will be > shallow or deep ? Long sentence that sounded too controversial to understand. 1) An aggregate can't have ANY user-declared constructors or destructors. 2) Returning objects of class type results with RVO (no copies made). 3) Your concept of shallow copies is also hard to understand: > With shallow I mean : every automatic member not requiring > new or new [], with deep copy I mean exact copy (or even the > temporary itself ...). What are automatic members? Snipping the rest since it discusses more of making constructors to aggregate.
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 01:18 +0200 |
| Message-ID | <qgj1kg$h7s$1@dont-email.me> |
| In reply to | #67048 |
On 16/07/19 00:40, Öö Tiib wrote: > On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: >> I've been a long time far from C++ and I realize I have >> forgotten most, and moreover don't understand "modern" C++ >> .... anyway >> >> When in a function (member or not is irrelevant) I build an >> aggregate object (class / struct, possibly nested with >> other), and this aggregate has a DEFAULT public constructor >> which does not resort to new or new [], but then the said >> former function invokes some class methods that DO some >> dynamic allocation, and then the function returns passing >> outside a copy by-value of the built object to the caller, >> placed "partially" on the stack, the final copy will be >> shallow or deep ? > > Long sentence that sounded too controversial to sorry for my tangled english :\ > understand. 1) An aggregate can't have ANY user-declared I realize now I have mis-used this word (that had a precise meaning in C++!). So let replace it with "class/struct type object" > constructors or destructors. 2) Returning objects of class > type results with RVO (no copies made). could you explain this acronym ? > 3) Your concept > of shallow copies is also hard to understand: only automatic (on stack) members, no "remote" (dynamic) data allocated with new / new [] > >> With shallow I mean : every automatic member not requiring >> new or new [], with deep copy I mean exact copy (or even the >> temporary itself ...). > > What are automatic members? the ones completely contained in the object itself. I took the term automatic from "automatic" variables (with local scope, built on the stack) contrasted with "dynamic" variables (allocated manually from the heap and whose lifetime is to be manually managed too). > Snipping the rest since it > discusses more of making constructors to aggregate. you are right, I mis-used the term ! I just meant some object containing both some automatic members and also some dynamically allocated ones. TY -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-07-15 21:12 -0400 |
| Message-ID | <qgj89q$dr3$1@dont-email.me> |
| In reply to | #67049 |
On 7/15/19 7:18 PM, Soviet_Mario wrote: > On 16/07/19 00:40, Öö Tiib wrote: >> On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: ... >> constructors or destructors. 2) Returning objects of class type >> results with RVO (no copies made). > > could you explain this acronym ? "... the return statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function call by copy-initialization (11.6) from the operand. [ Note: A return statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function. A copy operation associated with a return statement may be elided or converted to a move operation if an automatic storage duration variable is returned." (9.6.3p2) RVO is abbreviation for "Return Value Optimization", and refers to cases in which a call to a copy constructor could in principle occur, but may be elided. That clause uses a couple of terms that you might not be familiar with: "A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function. A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears." (6.10p1). >> 3) Your concept of shallow copies is also hard to understand: > > only automatic (on stack) members, no "remote" (dynamic) data > allocated with new / new []> >> >>> With shallow I mean : every automatic member not requiring new or >>> new [], with deep copy I mean exact copy (or even the temporary >>> itself ...). >> >> What are automatic members? > > the ones completely contained in the object itself. I took the term > automatic from "automatic" variables (with local scope, built on the > stack) contrasted with "dynamic" variables (allocated manually from > the heap and whose lifetime is to be manually managed too). The standard term that matches what you mean is "non-static data member" (12.2p3). Note that the storage duration of a non-static data member is always the same as the storage duration of the containing object (6.7.5p1). Non-static data members can therefore have static, automatic, dynamic, or thread storage duration. >> Snipping the rest since it discusses more of making constructors to >> aggregate. > > you are right, I mis-used the term ! I just meant some object > containing both some automatic members and also some dynamically > allocated ones. TY A member is not dynamically allocated unless it is a non-static data member of a dynamically allocated object, in which case all non-static data members of the same object are dynamically allocated. I suspect that what you mean is members that are pointers to dynamically allocated memory. Pointers are not distinguished by the storage duration of the objects that they point at, any pointer can point at any suitable object, regardless of that object's storage duration. Therefore, it's not appropriate for the compiler to automatically free the memory a pointer points at. It is the responsibility of the programmer, to make sure that the memory it points at is in fact deallocated, when appropriate, and only if it was dynamically allocated. That's one of the things that user-defined destructors are used for - to make sure the memory is deallocated. Smart pointers are specialized classes that have destructors that, in some cases, automatically deallocate the memory that they contain a pointer to.
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 14:28 +0200 |
| Message-ID | <qgkft8$c20$1@dont-email.me> |
| In reply to | #67050 |
On 16/07/19 03:12, James Kuyper wrote: > On 7/15/19 7:18 PM, Soviet_Mario wrote: >> On 16/07/19 00:40, Öö Tiib wrote: >>> On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: > ... >>> constructors or destructors. 2) Returning objects of class type >>> results with RVO (no copies made). >> >> could you explain this acronym ? > > "... the return statement initializes the glvalue result or prvalue > result object of the (explicit or implicit) function call by > copy-initialization (11.6) from the operand. [ Note: A return statement > can involve an invocation of a constructor to perform a copy or move of > the operand if it is not a prvalue or if its type differs from the return > type of the function. A copy operation associated with a return > statement may be elided or converted to a move operation if an automatic > storage duration variable is returned." (9.6.3p2) > > RVO is abbreviation for "Return Value Optimization", and refers to cases > in which a call to a copy constructor could in principle occur, but may > be elided. > > That clause uses a couple of terms that you might not be familiar with: > > "A glvalue is an expression whose evaluation determines the identity of > an object, bit-field, or function. > A prvalue is an expression whose evaluation initializes an object or a > bit-field, or computes the value of the operand of an operator, as > specified by the context in which it appears." (6.10p1). > >>> 3) Your concept of shallow copies is also hard to understand: >> >> only automatic (on stack) members, no "remote" (dynamic) data >> allocated with new / new []> >>> >>>> With shallow I mean : every automatic member not requiring new or >>>> new [], with deep copy I mean exact copy (or even the temporary >>>> itself ...). >>> >>> What are automatic members? >> >> the ones completely contained in the object itself. I took the term >> automatic from "automatic" variables (with local scope, built on the >> stack) contrasted with "dynamic" variables (allocated manually from >> the heap and whose lifetime is to be manually managed too). > > The standard term that matches what you mean is "non-static data member" > (12.2p3). Note that the storage duration of a non-static data member is > always the same as the storage duration of the containing object > (6.7.5p1). Non-static data members can therefore have static, automatic, > dynamic, or thread storage duration. could you give me a reference of the manual you are referring to with the notation "12.2p3" etc ? I mean a reference to some online manual > >>> Snipping the rest since it discusses more of making constructors to >>> aggregate. >> >> you are right, I mis-used the term ! I just meant some object >> containing both some automatic members and also some dynamically >> allocated ones. TY > > A member is not dynamically allocated unless it is a non-static data > member of a dynamically allocated object, in which case all non-static > data members of the same object are dynamically allocated. I am referring to objects of a class derived from MyString, that have some automatic and / or static data members, existing even for "empty" MyStrings, and some dynamic content (created and destroyed using new char [] / delege [] an empty MyString can be built without calling any new char [] / delege [], but further elaboration, which assigns content, requires it, or even reallocation. So I was asking about the behaviour of returning data for these objects whose memory "footprint" is hybrid and also variable depending on context. I need to understand of glvalue and grvalue, as I can only recall the concepts of R-value and L-value, to one side, and value-types vs reference-types on the other, but I surely have to complete the definitions I understand > > I suspect that what you mean is members that are pointers to dynamically > allocated memory. exactly : some "rich" strings, that have a constant framework of members and an "optional" content, on the HEAP, pointed to by an automatic pointer member > Pointers are not distinguished by the storage duration yes I know pointers are not, but I have doubts for the actual content pointed to. Avoiding DEEP copying (just copying the pointer, and thus having more than one pointer targeting the same content, would be destructive, as each MyString must have is private and locale space reserved, and modifying it must not affect others) > of the objects that they point at, any pointer can point at any suitable > object, regardless of that object's storage duration. ok, but my doubt was about : is it dynamic memory automatically duplicated (skeptic) ? Is NEVER duplicated ? (harmful). Is the whole regulated by invoking the COPY-constructor, so that it can decide ? > Therefore, it's > not appropriate for the compiler to automatically free the memory a > pointer points at. yes, but my doubt was more limited, I try to repeat it. In the CALLEE, building a return value (passed not by address or reference, just by-value => an hint to copy data), some dynamic allocation is done explicitly. The copy received by the caller, then would ... 1) receive NO data at all (I'm not saying the compiler has ever freed it, simply it remains lost, inaccessible, resultin in a leak) 2) receive a link to the same content, copied in another pointer 3) receive a copy of the dynamic data placed elsewhere (which seems not reasonable if it was up to the compiler to reallocate some room, transfer the data, deallocate the CALLEE copy, but maybe this would be done if a COPY constructor is delegated, and this always makes a copy ... well this scenario seems heavy and inefficient, it would be good to just copy automatic members so that just one reference to data would exist after return, the one of the caller) > It is the responsibility of the programmer, to make > sure that the memory it points at is in fact deallocated, when > appropriate, and this is managed now overloading operator = and also in the copy constructor. It would be safe but inefficient to have this same code when returning objects by value that were just built (in the case of initialization it would be inevitable instead, as there is no such duplicated operation) > and only if it was dynamically allocated. That's one of the > things that user-defined destructors are used for - to make sure the > memory is deallocated. > > Smart pointers are specialized classes that have destructors that, in > some cases, automatically deallocate the memory that they contain a > pointer to. I don't master them at all .... by now I prefer to just resort to things I understand well. And C++ has changed very very much in 10-15 years I had almost abandoned it :\ > -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-07-16 09:47 -0400 |
| Message-ID | <qgkkif$75t$1@dont-email.me> |
| In reply to | #67059 |
On 7/16/19 8:28 AM, Soviet_Mario wrote: > On 16/07/19 03:12, James Kuyper wrote: >> On 7/15/19 7:18 PM, Soviet_Mario wrote: >>> On 16/07/19 00:40, Öö Tiib wrote: >>>> On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: ... >> The standard term that matches what you mean is "non-static data member" >> (12.2p3). Note that the storage duration of a non-static data member is >> always the same as the storage duration of the containing object >> (6.7.5p1). Non-static data members can therefore have static, automatic, >> dynamic, or thread storage duration. > > could you give me a reference of the manual you are > referring to with the notation "12.2p3" etc ? > I mean a reference to some online manual It's not a "manual", it's n4659.pdf, a free draft version of the C++ standard: the draft is almost exactly the same as the official C++2017 standard, so it's hard for me to justify paying the significant extra cost of buying the actual standard. You can find it at <http://www.open-std.org/jtc1/sc22/wg21/docs/standards> ... >> A member is not dynamically allocated unless it is a non-static data >> member of a dynamically allocated object, in which case all non-static >> data members of the same object are dynamically allocated. > > I am referring to objects of a class derived from MyString, > that have some automatic and / or static data members, Will you please stop using "automatic" for that purpose? The correct term is "non-static". Given the following declarations, occurring inside a function body: MyString Automatic; MyString *Dynamic = new MyString(); static MyString Static; thread_local MyString ThreadLocal; and assuming that MyString contains a non-static data member named "data", then Automatic.data has automatic storage duration, Dynamic->data has dynamic storage duration, Static.data has static storage duration, and ThreadLocal.data has thread local storage duration. Being "automatic" is NOT a characteristic of the "data" member, only of it's containing object. If that member is a pointer to dynamically allocated memory, then *data has dynamic storage duration, regardless of what storage duration data itself has. ... > So I was asking about the behaviour of returning data for > these objects whose memory "footprint" is hybrid and also > variable depending on context. > > I need to understand of glvalue and grvalue, as I can only > recall the concepts of R-value and L-value, to one side, and > value-types vs reference-types on the other, but I surely > have to complete the definitions I understand glvalue and prvalue are refinements of the concepts of l-value and r-value, respectively. Frankly, I haven't fully familiarized myself with the details of that refinement. ... >> of the objects that they point at, any pointer can point at any suitable >> object, regardless of that object's storage duration. > > ok, but my doubt was about : is it dynamic memory > automatically duplicated (skeptic) ? No. > Is NEVER duplicated ? It's duplicated whenever you explicitly write code duplicating it. > (harmful). Is the whole regulated by invoking the > COPY-constructor, so that it can decide ? Only if you explicitly define the copy-constructor, and your user-written copy constructor makes that decision. For example, there is a strategy, called Copy-On-Write (COW), which means that all direct copying, whether by assignment, construction, or conversion, involves copying over only a pointer to the actual memory being managed. As a result, a single block of memory might be shared between many different containers. However, as soon as a write needs to be done, the container in which the write occurred would copy the shared memory to a new location, and then stop participating in the share. Only then would it write to the new location. That's all managed by user-written code - default constructors and default assignment operator overloads never do anything that sophisticated. I gather that COW used to be common in implementations of std::string, but that it has since gone out of favor. My purpose in bringing it up is only to point out that there are more sophisticated alternatives to your simple shallow/deep copy distinction. >> Therefore, it's >> not appropriate for the compiler to automatically free the memory a >> pointer points at. > > yes, but my doubt was more limited, I try to repeat it. > > In the CALLEE, building a return value (passed not by > address or reference, just by-value => an hint to copy > data), some dynamic allocation is done explicitly. > The copy received by the caller, then would ... > 1) receive NO data at all (I'm not saying the compiler has > ever freed it, simply it remains lost, inaccessible, > resultin in a leak) No. > 2) receive a link to the same content, copied in another pointer If the object contains a pointer to the content, then a default constructor or a default assignment operator overload will simply copy that pointer. > 3) receive a copy of the dynamic data placed elsewhere In order to get that behavior, you have to define your own non-default constructors and non-default assignment operator overloads. ... >> It is the responsibility of the programmer, to make >> sure that the memory it points at is in fact deallocated, when >> appropriate, > > and this is managed now overloading operator = and also in > the copy constructor. > It would be safe but inefficient to have this same code when > returning objects by value that were just built (in the case > of initialization it would be inevitable instead, as there > is no such duplicated operation) You misunderstand: returning objects by value is NOT a separate kind of operation. It is performed by using constructors - a copy constructor is sometime necessary; but constructing the return value directly in it's final location is often a permitted optimization. What happens depends entirely upon what you've defined those functions to do, or if you've let them be defined by default, it depends upon what the default versions do. >> and only if it was dynamically allocated. That's one of the >> things that user-defined destructors are used for - to make sure the >> memory is deallocated. >> >> Smart pointers are specialized classes that have destructors that, in >> some cases, automatically deallocate the memory that they contain a >> pointer to. > > I don't master them at all .... by now I prefer to just > resort to things I understand well. I recommend learning about smart pointers when you have time, but I also agree that you should not use them until you've had time to learn about them. > And C++ has changed very very much in 10-15 years I had > almost abandoned it :\ Among the most important changes that are relevant to this discussion is "move" semantics. I'm not fully up to speed on move semantics, but my understanding is that if you move one string into another string, only the pointer to the contained data is copied, not the data itself, and the original string ends up empty. The actual semantics of "move" depends upon how you define move constructors or move assignment operator overloads. As a general rule, if it is permissible to leave the source empty, doing a move rather than a copy is usually more efficient, and seldom less efficient.
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 17:16 +0200 |
| Message-ID | <qgkpou$6h2$1@dont-email.me> |
| In reply to | #67064 |
On 16/07/19 15:47, James Kuyper wrote: > On 7/16/19 8:28 AM, Soviet_Mario wrote: >> On 16/07/19 03:12, James Kuyper wrote: >>> On 7/15/19 7:18 PM, Soviet_Mario wrote: >>>> On 16/07/19 00:40, Öö Tiib wrote: >>>>> On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: > ... >>> The standard term that matches what you mean is "non-static data member" >>> (12.2p3). Note that the storage duration of a non-static data member is >>> always the same as the storage duration of the containing object >>> (6.7.5p1). Non-static data members can therefore have static, automatic, >>> dynamic, or thread storage duration. >> >> could you give me a reference of the manual you are >> referring to with the notation "12.2p3" etc ? >> I mean a reference to some online manual > It's not a "manual", it's n4659.pdf, a free draft version of the C++ > standard: the draft is almost exactly the same as the official C++2017 > standard, so it's hard for me to justify paying the significant extra > cost of buying the actual standard. You can find it at > <http://www.open-std.org/jtc1/sc22/wg21/docs/standards> Thanks, I'm gonna get the DOC ! > > ... >>> A member is not dynamically allocated unless it is a non-static data >>> member of a dynamically allocated object, in which case all non-static >>> data members of the same object are dynamically allocated. >> >> I am referring to objects of a class derived from MyString, >> that have some automatic and / or static data members, > > Will you please stop using "automatic" for that purpose? The correct > term is "non-static". mmm, the fact is : to me non-static seems a WIDER definition than automatic, as dynamic also is non-static :) > Given the following declarations, occurring inside > a function body: > > MyString Automatic; > MyString *Dynamic = new MyString(); > static MyString Static; > thread_local MyString ThreadLocal; > > and assuming that MyString contains a non-static data member named > "data", then Automatic.data has automatic storage duration, > Dynamic->data has dynamic storage duration, Static.data has static > storage duration, and ThreadLocal.data has thread local storage > duration. Being "automatic" is NOT a characteristic of the "data" > member, only of it's containing object. uhm .... :\ > > If that member is a pointer to dynamically allocated memory, then *data > has dynamic storage duration, regardless of what storage duration data > itself has. this IS clear ! > > ... >> So I was asking about the behaviour of returning data for >> these objects whose memory "footprint" is hybrid and also >> variable depending on context. >> >> I need to understand of glvalue and grvalue, as I can only >> recall the concepts of R-value and L-value, to one side, and >> value-types vs reference-types on the other, but I surely >> have to complete the definitions I understand > > glvalue and prvalue are refinements of the concepts of l-value and > r-value, respectively. Frankly, I haven't fully familiarized myself with > the details of that refinement. OK ... no problem, maybe I won't need to refine too :) > > ... >>> of the objects that they point at, any pointer can point at any suitable >>> object, regardless of that object's storage duration. >> >> ok, but my doubt was about : is it dynamic memory >> automatically duplicated (skeptic) ? > > No. > >> Is NEVER duplicated ? > > It's duplicated whenever you explicitly write code duplicating it. OK : I have written the copy-constructor, yes > >> (harmful). Is the whole regulated by invoking the >> COPY-constructor, so that it can decide ? > > Only if you explicitly define the copy-constructor, and your > user-written copy constructor makes that decision. > > For example, there is a strategy, called Copy-On-Write (COW), which yes...no ! No, I don't want COW even if it is faster and maybe more parsimonious. I just need code safer and simpler to read. > means that all direct copying, whether by assignment, construction, or > conversion, involves copying over only a pointer to the actual memory > being managed. As a result, a single block of memory might be shared > between many different containers. yes it's like the SNAPSHOTS on virtual machine disks : they actually record only the changes of status, not the entire status of the file system. Also BTRFS snapshots work like that. I'd prefer more "synced" status of each object than deferred writes > However, as soon as a write needs to > be done, the container in which the write occurred would copy the shared > memory to a new location, and then stop participating in the share. Only > then would it write to the new location. > > That's all managed by user-written code - default constructors and > default assignment operator overloads never do anything that sophisticated. > > I gather that COW used to be common in implementations of std::string, > but that it has since gone out of favor. My purpose in bringing it up is > only to point out that there are more sophisticated alternatives to your > simple shallow/deep copy distinction. agreed. I had not even thought about such more advanced features as I just need to have simple and solid code : it won't be performance intensive > > >>> Therefore, it's >>> not appropriate for the compiler to automatically free the memory a >>> pointer points at. >> >> yes, but my doubt was more limited, I try to repeat it. >> >> In the CALLEE, building a return value (passed not by >> address or reference, just by-value => an hint to copy >> data), some dynamic allocation is done explicitly. >> The copy received by the caller, then would ... >> 1) receive NO data at all (I'm not saying the compiler has >> ever freed it, simply it remains lost, inaccessible, >> resultin in a leak) > > No. > >> 2) receive a link to the same content, copied in another pointer > > If the object contains a pointer to the content, then a default > constructor or a default assignment operator overload will simply copy > that pointer. > >> 3) receive a copy of the dynamic data placed elsewhere > > In order to get that behavior, you have to define your own non-default > constructors and non-default assignment operator overloads. OK clear: I should not expect strange hidden behaviour. I'm getting maybe close to some compilable code .... then I'll inspect all in the Debugger. Some times is more useful to observe live than to try to figure out theoretically > > ... >>> It is the responsibility of the programmer, to make >>> sure that the memory it points at is in fact deallocated, when >>> appropriate, >> >> and this is managed now overloading operator = and also in >> the copy constructor. >> It would be safe but inefficient to have this same code when >> returning objects by value that were just built (in the case >> of initialization it would be inevitable instead, as there >> is no such duplicated operation) > > You misunderstand: returning objects by value is NOT a separate kind of > operation. It is performed by using constructors - a copy constructor is > sometime necessary; but constructing the return value directly in it's > final location is often a permitted optimization. What happens depends > entirely upon what you've defined those functions to do, or if you've > let them be defined by default, it depends upon what the default > versions do. > >>> and only if it was dynamically allocated. That's one of the >>> things that user-defined destructors are used for - to make sure the >>> memory is deallocated. >>> >>> Smart pointers are specialized classes that have destructors that, in >>> some cases, automatically deallocate the memory that they contain a >>> pointer to. >> >> I don't master them at all .... by now I prefer to just >> resort to things I understand well. > > I recommend learning about smart pointers when you have time, but I also > agree that you should not use them until you've had time to learn about > them. > >> And C++ has changed very very much in 10-15 years I had >> almost abandoned it :\ > > Among the most important changes that are relevant to this discussion is > "move" semantics. I'm not fully up to speed on move semantics, but my > understanding is that if you move one string into another string, only > the pointer to the contained data is copied, not the data itself, and > the original string ends up empty. The actual semantics of "move" > depends upon how you define move constructors or move assignment > operator overloads. As a general rule, if it is permissible to leave the > source empty, doing a move rather than a copy is usually more efficient, > and seldom less efficient. mmm ... unheard of .... thanks for the hint ! > -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-07-16 10:30 -0700 |
| Message-ID | <39ef7c7f-0fa2-47ae-9daf-898f7772bc3e@googlegroups.com> |
| In reply to | #67067 |
On Tuesday, July 16, 2019 at 11:16:57 AM UTC-4, Soviet_Mario wrote: > On 16/07/19 15:47, James Kuyper wrote: > > On 7/16/19 8:28 AM, Soviet_Mario wrote: ... > >> I am referring to objects of a class derived from MyString, > >> that have some automatic and / or static data members, > > > > Will you please stop using "automatic" for that purpose? The correct > > term is "non-static". > > mmm, the fact is : to me non-static seems a WIDER definition > than automatic, as dynamic also is non-static :) Yes, it is wider. All members are either member functions, static data members, non-static data members, nested classes, or typedef members. The problem is that "automatic", as that term is defined by the standard, doesn't describe a property of a class member - it describes a property of a particular instance of a class, and that property applies to all of the non-static data members of that instance. It's not meaningful to talk about some of the members being automatic and others being dynamic. This isn't just pedantry - it's directly relevant to the issue you're worrying about. Consider a class containing just two members: a pointer to a dynamically allocated array and a count of the number of elements in that array. I suspect that you would describe the count as "automatic"; I'm not sure exactly what you would say about the pointer. The relevant facts are that both the count and the pointer are non-static data members. They both always have the same storage duration - which is the storage duration of the object that they are part of. The memory that the pointer points at is dynamically allocated - but that's not a feature of the pointer member, it's a feature of the way that the class code uses that pointer. A default copy will copy both the value of the count and the value of the pointer, and will not do anything special regarding the memory that the pointer points at. If that's not what you want to have happen, you'll have to write a constructor that actually does do what you want to have happen.
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 19:44 +0200 |
| Message-ID | <qgl2eh$ue6$1@dont-email.me> |
| In reply to | #67068 |
On 16/07/19 19:30, James Kuyper wrote: > On Tuesday, July 16, 2019 at 11:16:57 AM UTC-4, Soviet_Mario wrote: >> On 16/07/19 15:47, James Kuyper wrote: >>> On 7/16/19 8:28 AM, Soviet_Mario wrote: > ... >>>> I am referring to objects of a class derived from MyString, >>>> that have some automatic and / or static data members, >>> >>> Will you please stop using "automatic" for that purpose? The correct >>> term is "non-static". >> >> mmm, the fact is : to me non-static seems a WIDER definition >> than automatic, as dynamic also is non-static :) > > Yes, it is wider. All members are either member functions, static data > members, non-static data members, nested classes, or typedef members. > > The problem is that "automatic", as that term is defined by the > standard, doesn't describe a property of a class member - it describes a > property of a particular instance of a class, and that property applies > to all of the non-static data members of that instance. It's not > meaningful to talk about some of the members being automatic and others > being dynamic. > > This isn't just pedantry - oh, friend, never said or even thought so !! I am just old-fashioned minded, an era when autopointers or worse AUTO determination of the return value by its context was really far fetched. So I was just trying to justify myself, my way of thinking. > it's directly relevant to the issue you're > worrying about. Consider a class containing just two members: a pointer > to a dynamically allocated array and a count of the number of elements > in that array. I suspect that you would describe the count as > "automatic"; both the members are automatic. The pointer also IS. The buffer pointed to, on the contrary, I would not call it automatic, but dynamic. > I'm not sure exactly what you would say about the pointer. that in itself is automatic, as it still exist (it takes up 4 or 8 byte even if it contains NULLPTR) > The relevant facts are that both the count and the pointer are > non-static data members. They both always have the same storage duration I agree in fact > - which is the storage duration of the object that they are part of. The > memory that the pointer points at is dynamically allocated - but that's > not a feature of the pointer member, yes it's not an intrinsical property of it, but this is not really important for the passing out mechanism > it's a feature of the way that the > class code uses that pointer. yes, now I have understood that I can rely on the fact that the compiler itself generates no hidden code having side effects on dynamic data, except for calling copy-constructor and destructor, which I have to write myself. And also that I cannot make assumptions whether or not the copy constructor is actually called or some optimization (like building the returned object in a location provided by the CALLER itself, or copying it back by MY copy-ctor) eliding copy happens. > > A default copy will copy both the value of the count and the value of > the pointer, and will not do anything special regarding the memory that > the pointer points at. I have my hand written copy-ctor that copies data, so I should be sure no overlapping ownership could take place > If that's not what you want to have happen, > you'll have to write a constructor that actually does do what you want > to have happen. > yes. Many thanks to you and every one else. Some rust removed successfully :) :) CIAO -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | Rosario19 <Ros@invalid.invalid> |
|---|---|
| Date | 2019-07-23 09:28 +0200 |
| Message-ID | <3gddjedd4f3epst54kl6shca9qj71p89n6@4ax.com> |
| In reply to | #67059 |
On Tue, 16 Jul 2019 14:28:23 +0200, Soviet_Mario wrote: >I am referring to objects of a class derived from MyString, >that have some automatic and / or static data members, >existing even for "empty" MyStrings, and some dynamic >content (created and destroyed using new char [] / delege [] > >an empty MyString can be built without calling any new char >[] / delege [], but further elaboration, which assigns >content, requires it, or even reallocation. > >So I was asking about the behaviou in un debugger, puoi vedere le funzioni che vengono chiamate... in generale ogni obj non tuo, ha propri costruttori e tutto va bene no leak ecc se ci sono object tuoi, che abbisognano memoria dinamica allora devi stare attento... per quel che mi riguarda in qualche esercizio la cosa che avrei fatto, per chiarire il fatto della memoria, è stato (ri)costruire malloc free e new e vedere come la memoria veniva utilizzata nei obj che avevo costruito, in particolare vedere se c'erano leak
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-07-15 20:22 -0700 |
| Message-ID | <d2d4833c-f06b-4b49-bbee-3e9eab0ffec2@googlegroups.com> |
| In reply to | #67049 |
On Tuesday, 16 July 2019 02:18:51 UTC+3, Soviet_Mario wrote: > On 16/07/19 00:40, Öö Tiib wrote: > > > constructors or destructors. 2) Returning objects of class > > type results with RVO (no copies made). > > could you explain this acronym ? I see James Kuyper made decent effort to explain it. In practice the implementations pass the address for return value of class type to function like other arguments. The function is allowed to construct the object that it is going to return at that address and so elide copying when returning. It often surprises people who wrote side effects to copy or move constructors or destructors. > > 3) Your concept > > of shallow copies is also hard to understand: > > only automatic (on stack) members, no "remote" (dynamic) > data allocated with new / new [] > > > > >> With shallow I mean : every automatic member not requiring > >> new or new [], with deep copy I mean exact copy (or even the > >> temporary itself ...). > > > > What are automatic members? > > the ones completely contained in the object itself. > I took the term automatic from "automatic" variables (with > local scope, built on the stack) contrasted with "dynamic" > variables (allocated manually from the heap and whose > lifetime is to be manually managed too). Hmm. Making efficient manual management of resources with C++ has become quite complicated topic. It can take more than week to read and to understand the nuances of "RAII", "rule of three", "copy-swap idiom", "rule of five", "rule of zero" and "rule of four (and half)". People who write about one of those tend to oversimplify the issue. For example they typically forget to tell that with dynamically polymorphic class hierarchy (with virtual functions) all exposed copying, moving or swapping may cause sliced objects or worse. So protect or =delete all that and use factories and cloning with such hierarchies instead.
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 14:37 +0200 |
| Message-ID | <qgkge2$f5c$1@dont-email.me> |
| In reply to | #67053 |
On 16/07/19 05:22, Öö Tiib wrote: > On Tuesday, 16 July 2019 02:18:51 UTC+3, Soviet_Mario wrote: >> On 16/07/19 00:40, Öö Tiib wrote: >> >>> constructors or destructors. 2) Returning objects of class >>> type results with RVO (no copies made). >> >> could you explain this acronym ? > > I see James Kuyper made decent effort to explain it. sure, he was kind. I just have to collect a copy of the document he was referring to > In practice the implementations pass the address for > return value of class type to function like other arguments. do you mean the CALLER passes an "hidden" further parameter to the CALLEE indicating where to place the (automatic part of the) built object ? In this case, the inefficient COPY-constructor would not be invoked ... > The function is allowed to construct the object that it is going > to return at that address and so elide copying when returning. intresting ... I knew nothing about this mechanism > It often surprises people who wrote side effects to copy or > move constructors or destructors. I could not understand what you meant ... I had to add the copy constructor to just clone-initialize objects explicitly. I thought (wrongly) it would have been invoked also in returning objects on the stack. But if this does not happen, much better ! > >>> 3) Your concept >>> of shallow copies is also hard to understand: >> >> only automatic (on stack) members, no "remote" (dynamic) >> data allocated with new / new [] >> >>> >>>> With shallow I mean : every automatic member not requiring >>>> new or new [], with deep copy I mean exact copy (or even the >>>> temporary itself ...). >>> >>> What are automatic members? >> >> the ones completely contained in the object itself. >> I took the term automatic from "automatic" variables (with >> local scope, built on the stack) contrasted with "dynamic" >> variables (allocated manually from the heap and whose >> lifetime is to be manually managed too). > > Hmm. > > Making efficient manual management of resources with C++ > has become quite complicated topic. I was afraid so, but I have to do some MyString class, and there the dynamic management is unavoidable I fear > It can take more than week to read and to understand the > nuances of "RAII", "rule of three", "copy-swap idiom", > "rule of five", "rule of zero" and "rule of four (and half)". I had just read about resource acquisition is initialization. Never heard of the other bibl. > > People who write about one of those tend to oversimplify the issue. > For example they typically forget to tell that with dynamically > polymorphic class hierarchy (with virtual functions) all exposed > copying, moving or swapping may cause sliced objects or worse. > So protect or =delete all that and use factories and cloning > with such hierarchies instead. I am still not using virtual classes/members. And not even inheritance of the kind IS-A (I tend to use the HAS-A pattern, which I'm more confident of) actually I'm using C++ more like "a better C" and little more, or C-with-templates. > -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2019-07-17 01:41 -0700 |
| Message-ID | <ffa24f68-eda3-42f0-860b-2544eb158648@googlegroups.com> |
| In reply to | #67060 |
On Tuesday, 16 July 2019 15:37:32 UTC+3, Soviet_Mario wrote: > On 16/07/19 05:22, Öö Tiib wrote: > > > In practice the implementations pass the address for > > return value of class type to function like other arguments. > > do you mean the CALLER passes an "hidden" further parameter > to the CALLEE indicating where to place the (automatic part > of the) built object ? > In this case, the inefficient COPY-constructor would not be > invoked ... Yes, there is hidden parameter pointing at uninitialized memory. > > The function is allowed to construct the object that it is going > > to return at that address and so elide copying when returning. > > intresting ... I knew nothing about this mechanism Also where copy elision is allowed but compiler does not find a way to elide copy there it is typically required to move if move constructors are available. Read that too, it is less formal and accurate but bit easier to read than standard: https://en.cppreference.com/w/cpp/language/copy_elision > > > It often surprises people who wrote side effects to copy or > > move constructors or destructors. > > I could not understand what you meant ... > I had to add the copy constructor to just clone-initialize > objects explicitly. > I thought (wrongly) it would have been invoked also in > returning objects on the stack. But if this does not happen, > much better ! I meant that people sometimes add side effects to their copy/move constructors and destructors. For example output to some log. Then are surprised to not see the log entries they expected. > > > >>> 3) Your concept > >>> of shallow copies is also hard to understand: > >> > >> only automatic (on stack) members, no "remote" (dynamic) > >> data allocated with new / new [] > >> > >>> > >>>> With shallow I mean : every automatic member not requiring > >>>> new or new [], with deep copy I mean exact copy (or even the > >>>> temporary itself ...). > >>> > >>> What are automatic members? > >> > >> the ones completely contained in the object itself. > >> I took the term automatic from "automatic" variables (with > >> local scope, built on the stack) contrasted with "dynamic" > >> variables (allocated manually from the heap and whose > >> lifetime is to be manually managed too). > > > > Hmm. > > > > Making efficient manual management of resources with C++ > > has become quite complicated topic. > > I was afraid so, but I have to do some MyString class, and > there the dynamic management is unavoidable I fear Usual advice is to use standard library classes (like std::string) as data members (or sometimes as private bases) of your class. These do memory management for you and so you have to write only the special functionality of your MyString. > > It can take more than week to read and to understand the > > nuances of "RAII", "rule of three", "copy-swap idiom", > > "rule of five", "rule of zero" and "rule of four (and half)". > > I had just read about resource acquisition is > initialization. Never heard of the other bibl. For historic reasons the C++ compiler generates some public code for classes implicitly (if it can). That code can be correct or incorrect depending on logic of class and so people have made rules how to ensure that it does not cause any issues. > > People who write about one of those tend to oversimplify the issue. > > For example they typically forget to tell that with dynamically > > polymorphic class hierarchy (with virtual functions) all exposed > > copying, moving or swapping may cause sliced objects or worse. > > So protect or =delete all that and use factories and cloning > > with such hierarchies instead. > > > I am still not using virtual classes/members. > And not even inheritance of the kind IS-A (I tend to use the > HAS-A pattern, which I'm more confident of) > > > actually I'm using C++ more like "a better C" and little > more, or C-with-templates. When you work alone then it is fine, but success is easier to achieve when using code written by others and so cooperating with others.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-07-16 15:04 +0300 |
| Message-ID | <qgkego$4q8$1@dont-email.me> |
| In reply to | #67046 |
On 16.07.2019 1:00, Soviet_Mario wrote: > > I've been a long time far from C++ and I realize I have forgotten most, > and moreover don't understand "modern" C++ .... anyway > > When in a function (member or not is irrelevant) I build an aggregate > object (class / struct, possibly nested with other), and this aggregate > has a DEFAULT public constructor which does not resort to new or new [], > but then the said former function invokes some class methods that DO > some dynamic allocation, and then the function returns passing outside a > copy by-value of the built object to the caller, placed "partially" on Your question is not very clear, consider to add some code examples to make it clearer. In general, defining classes which do their own own low-level dynamic memory allocation is tricky. One typically needs to define custom constructors, assignments and destructors. Fortunately enough, there is near zero need to do such low-level dynamic allocation nowadays in C++, as it's properly done and encapsulated in standard library classes like std::vector. If some objects really need to be dynamically allocated, like some OOP hierarchy objects, one should use std::make_unique() (or maybe std::make_shared() in special circumstances) and appropriate smartpointers. That said, the answer to your question is probably that by default the copies in C++ are "shallow" (a copy of a pointer or a standard smartpointer is just another pointer with the same value), to make it deep one needs to define custom copy and assignment operations. The latter is done e.g. by std::vector, so copying std::vector objects always copies the whole data array. hth Paavo
[toc] | [prev] | [next] | [standalone]
| From | Soviet_Mario <SovietMario@CCCP.MIR> |
|---|---|
| Date | 2019-07-16 14:42 +0200 |
| Message-ID | <qgkgn4$gko$1@dont-email.me> |
| In reply to | #67058 |
On 16/07/19 14:04, Paavo Helde wrote: > On 16.07.2019 1:00, Soviet_Mario wrote: >> >> I've been a long time far from C++ and I realize I have >> forgotten most, >> and moreover don't understand "modern" C++ .... anyway >> >> When in a function (member or not is irrelevant) I build >> an aggregate >> object (class / struct, possibly nested with other), and >> this aggregate >> has a DEFAULT public constructor which does not resort to >> new or new [], >> but then the said former function invokes some class >> methods that DO >> some dynamic allocation, and then the function returns >> passing outside a >> copy by-value of the built object to the caller, placed >> "partially" on > > Your question is not very clear, consider to add some code > examples to make it clearer. > > In general, defining classes which do their own own > low-level dynamic memory allocation is tricky. One typically > needs to define custom constructors, assignments and > destructors. > > Fortunately enough, there is near zero need to do such > low-level dynamic allocation nowadays in C++, as it's > properly done and encapsulated in standard library classes > like std::vector. It was my first attempt : std::vector and std::list, but I was unable to find the methods to do both dynamic reallocation (grow / shrink) with the former and also random access BY INDEX with the latter. > If some objects really need to be > dynamically allocated, like some OOP hierarchy objects, one > should use std::make_unique() (or maybe std::make_shared() > in special circumstances) and appropriate smartpointers. > > That said, the answer to your question is probably that by > default the copies in C++ are "shallow" (a copy of a pointer > or a standard smartpointer is just another pointer with the > same value), to make it deep one needs to define custom copy > and assignment operations. I have defined both, it seemed inevitable with read-write Strings > The latter is done e.g. by > std::vector, so copying std::vector objects always copies > the whole data array. I'll rescan the std:: types you adviced though :\ TY > > hth > Paavo > -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato)
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2019-07-16 16:15 +0300 |
| Message-ID | <qgkime$sfm$1@dont-email.me> |
| In reply to | #67061 |
On 16.07.2019 15:42, Soviet_Mario wrote: > On 16/07/19 14:04, Paavo Helde wrote: >> On 16.07.2019 1:00, Soviet_Mario wrote: >>> >>> I've been a long time far from C++ and I realize I have forgotten most, >>> and moreover don't understand "modern" C++ .... anyway >>> >>> When in a function (member or not is irrelevant) I build an aggregate >>> object (class / struct, possibly nested with other), and this aggregate >>> has a DEFAULT public constructor which does not resort to new or new [], >>> but then the said former function invokes some class methods that DO >>> some dynamic allocation, and then the function returns passing outside a >>> copy by-value of the built object to the caller, placed "partially" on >> >> Your question is not very clear, consider to add some code examples to >> make it clearer. >> >> In general, defining classes which do their own own low-level dynamic >> memory allocation is tricky. One typically needs to define custom >> constructors, assignments and destructors. >> >> Fortunately enough, there is near zero need to do such low-level >> dynamic allocation nowadays in C++, as it's properly done and >> encapsulated in standard library classes like std::vector. > > It was my first attempt : std::vector and std::list, but I was unable to > find the methods to do both dynamic reallocation (grow / shrink) with > the former and also random access BY INDEX with the latter. std::vector is perfectly capable to dynamically grow and shrink. Insert and erase elsewhere than in the end might be a bit slow if you have millions of elements, but one should not worry about it prematurely.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-07-16 10:07 -0400 |
| Message-ID | <qgklmb$duu$1@dont-email.me> |
| In reply to | #67061 |
On 7/16/19 8:42 AM, Soviet_Mario wrote: ... > It was my first attempt : std::vector and std::list, but I > was unable to find the methods to do both dynamic > reallocation (grow / shrink) The relevant methods are various overloads to insert() and erase(), as well as push_back() and pop_back(). If you simply want to expand the allocated memory without filling it immediately, use reserve(). If you want to shed unneeded allocated memory, use shrink_to_fit(). > with the former and also random > access BY INDEX with the latter. By it's vary nature std::list cannot support random access. If you need random access, you shouldn't be using a list. If you absolutely need use an index, std::next(list.begin(), n) will return an iterator referring to the n'th element of the list. This isn't true random access: it applies operator++() to the iterator n times, in order to get to that location.
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2019-07-17 07:36 +0000 |
| Message-ID | <qgmj6b$2ea1$1@adenine.netfront.net> |
| In reply to | #67046 |
Soviet_Mario <SovietMario@cccp.mir> wrote: > When in a function (member or not is irrelevant) I build an > aggregate object (class / struct, possibly nested with > other), and this aggregate has a DEFAULT public constructor > which does not resort to new or new [], but then the said > former function invokes some class methods that DO some > dynamic allocation, and then the function returns passing > outside a copy by-value of the built object to the caller, > placed "partially" on the stack, the final copy will be > shallow or deep ? It's up that type returned by that function how it behaves when copied. For example, if the returned type is std::vector, copying it will make a deep copy (although in this case that will most probably be skipped because of return value optimization). If the returned type is std::shared_ptr, copying it will, essentially, be a shallow copy (the managed object will not be copied; all std::shared_ptr instances copied from the original will share the same managed object). If it's your own type, your own class, that's being returned, then it's up to you how it behaves when copied. The first part of your question is completely unrelated to this and I don't really understand why you think it's relevant. It doesn't matter *where* that function is called from.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web