- [niubbo] aggregate types built in a function and returned by value (on stack). Shallow or Deep copy ? - 3 Updates
- how/why it is written ... int &numberRef; vs int& numberRef; - 3 Updates
- "Draft FAQ: Why does the C++ standard ship every three years?" by Herb Sutter - 1 Update
- What is wrong with my template gJoin() function? - 2 Updates
- Most Sacrilegious Code I've Ever Written - 4 Updates
- main2(), kernel_main (c/c++) - 4 Updates
- WxWidgets events question - 1 Update
Soviet_Mario <SovietMario@CCCP.MIR>: Jul 16 12:00AM +0200 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) |
"Öö Tiib" <ootiib@hot.ee>: Jul 15 03:40PM -0700 On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote: > 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. |
Soviet_Mario <SovietMario@CCCP.MIR>: Jul 16 01:18AM +0200 On 16/07/19 00:40, Öö Tiib wrote: >> 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 [] >> 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) |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jul 12 06:55PM -0400 On 7/12/19 6:12 PM, G G wrote: > along with, int* aPointer; > my question is why associate the *, or & the the type instead of the > name? i do understand it is a preference. A simple declaration consists of a decl-specifier-seq followed by an init-declarator-list (10.1p1). In this case, int is the decl-specifier-seq (10.1.7.2p1) and *aPointer or &numberRef are the only declarators in their respective init-declarator-lists (11.1p4). That distinction doesn't matter if the init-declarator-list only contains one declarator. However, if it contains two or more declarators, I consider it helpful to keep track of the fact that & and * only apply to the immediately following declarators, and not to any of the other declarators in the same list. I find it easier to do so if I keep a space between the decl-specifier-seq and the init-declarator-list, and if I don't insert a space between the * or & and the rest of the declartor that it is part of: int *aPointer, &numberRef; * applies only to aPointer, and & applies only to numberRef. If I wrote something like int* aPointer, aFunc(void); a newbie might easily make the mistake of thinking that aFunc() returns an int*, rather than an int. It's a minor advantage, and many people prefer not to declare more than one declator per declaration, so for them it's no advantage at all. |
Juha Nieminen <nospam@thanks.invalid>: Jul 15 08:33PM > my question is why associate the *, or & the the type instead of the > name? i do understand it is a preference. For some reason that I do not know (and possibly nobody does), when C was originally devised (although it might have come from a precursor language like B or BCPL, I don't know) they decided that the indicator for a pointer variable, ie. the asterisk, would be tied to the variable name rather than the type. In other words, the asterisk is not, in fact, part of the type at all, but a sort of indicator that "this variable is a pointer". This distinction can be seen, as some have pointed out, when declaring more than one variable in the same expression: int *x, *y, z; Here x and y are pointers, while z is not. The asterisk, the indicator that means "this is a pointer", is tied to the variable name, not the type. Of course this can become a bit confusing when types are used in contexts other than variable declarations. While C-style typedefs kind of still follow this principle (as typedef syntax is essentially just normal variable declaration syntax with just the 'typedef' keyword added at the very beginning): typedef int *IntPtr; it depends on your point of view whether this is now confusing or not: IntPtr ptr; because now the "this is a pointer" part is part of the type alias, rather than tied to the variable name. When a function returns a pointer, it also can become a bit confusing, if you follow that same convention: int *function(); The "this is a pointer" asterisk kind of is part of the return type, kind of isn't. It's a bit confusing. No wonder many prefer writing it like this for clarity: int* function(); which of course means the exact same thing, but is visually clearer. And yes, this is valid C (and C++): int *function1(), *function2(), function3(); even though it's quite rarely used. (I bet most C/C++ programmers weren't aware of that.) C++ makes this even more complicated because there are many more situations where types are used on their own, without any sort of variable (or function) name, such as: std::vector<int*> vec; Also here the asterisk kind of is part of the type, kind of isn't. It's all confusing. |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jul 15 11:03PM +0100 > precursor language like B or BCPL, I don't know) they decided that > the indicator for a pointer variable, ie. the asterisk, would be > tied to the variable name rather than the type. Neither B nor BCPL had types. C was originally "B with types". > int *function(); > The "this is a pointer" asterisk kind of is part of the return type, > kind of isn't. It's a bit confusing. The general idea (now rather battered by history and changes to the language) is that declarations mirror use. function is a function designator. To call it, you mirror the declaration: function() The result is a pointer. To dereference that pointer you again mirror the declaration and use *: *function() to get an int. This idea of having declarations mirror use, gave rise to declarations that have two parts: the base type (like int, double and so on) and what C calls a declarator where operators like *, () and [] decorate the name with the same priority as they appear in expressions. Knowing both the history and syntax of declarations, I can't stand seeing int* function(); but I know I am on the wrong side of history here, at least as far as C++ is concerned. I'm not going to defend it, but you wondered where it came from. > it like this for clarity: > int* function(); > which of course means the exact same thing, but is visually clearer. This is the form that used to confuse me. Not that I didn't understand it, but I'd worry the author may not know how types work in C++. Now that is it almost de rigeur to write it this way, there's no reason to worry -- the programmer is simply following standard advice -- it just looks odd to me, like writing - a+b where the spacing does not reflect the syntax. > int *function1(), *function2(), function3(); > even though it's quite rarely used. (I bet most C/C++ programmers > weren't aware of that.) Don't people learn the syntax of the languages they use anymore? (I'm joking, of course they don't, but C and C++ were designed in era when they did.) -- Ben. |
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 15 03:13PM -0500 "Draft FAQ: Why does the C++ standard ship every three years?" by Herb Sutter https://herbsutter.com/2019/07/13/draft-faq-why-does-the-c-standard-ship-every-three-years/ Interesting. And the embodiment of tough love, stay on schedule no matter what. Lynn |
Christian Gollwitzer <auriocus@gmx.de>: Jul 15 07:41AM +0200 Am 14.07.19 um 11:16 schrieb Heinz Müller: > Your code is wonderful! Everyone should code like that! ROFL |
G G <gdotone@gmail.com>: Jul 15 06:22AM -0700 On Saturday, July 6, 2019 at 11:54:28 AM UTC-4, Szyk Cech wrote: > best regards, > and thanks in advance > Szyk Cech ----------------------------- template < typename tContainer, typename tString > tString gJoin( const tContainer &aStringList, const tString &aDelimiter ) { tString lResult; for(tString lPart : aStringList) { if(lResult.size() > 0) lResult += aDelimiter; lResult += lPart; } return lResult; } |
Frederick Gotham <cauldwell.thomas@gmail.com>: Jul 15 02:10AM -0700 On Thursday, July 11, 2019 at 3:52:46 PM UTC+1, Öö Tiib wrote: > Your Parameter seems to be proxy to nothing. I don't see how it > can be useful even in unit test. OTOH big part of C++ code out there > is useless so it is not sacrilegious to write some more. I'm part of a team that writes the firmware for an embedded device. I was told that the firmware used a 3rd party library that has been updated from Version 1 to Version 2. Version 2 is very different, it has a different API. Different functions, different structs, different enums. After changing the Makefile for my own project code to accomodate version 2 of the 3rd party library, I got a load of compiler and linker errors. I needed to get the entire project to compile, so I made a header file called "fake_stuff.hpp" to accommodate the differences in the new version of the 3rd party library. I had to make that "Param" class to get everything to compile. |
"Öö Tiib" <ootiib@hot.ee>: Jul 15 03:32AM -0700 On Monday, 15 July 2019 12:10:30 UTC+3, Frederick Gotham wrote: > I was told that the firmware used a 3rd party library that has been updated from Version 1 to Version 2. Version 2 is very different, it has a different API. Different functions, different structs, different enums. > After changing the Makefile for my own project code to accomodate version 2 of the 3rd party library, I got a load of compiler and linker errors. > I needed to get the entire project to compile, so I made a header file called "fake_stuff.hpp" to accommodate the differences in the new version of the 3rd party library. I had to make that "Param" class to get everything to compile. I'm still confused about the whole scenario. I imagine template (like X) in the new interface of 3rd party library. That X expects template class argument (like X<T>). Implementation of that X expects result of address of operator applied to const instance of T to be default-convertible into pointer to mutable void and to unsigned? And then you wrote the Parameter to satisfy concept of that T. That sounds hard to believe so perhaps I am not understanding the whole story. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Jul 15 04:19AM -0700 On Monday, July 15, 2019 at 11:33:07 AM UTC+1, Öö Tiib wrote: > the Parameter to satisfy concept of that T. > That sounds hard to believe so perhaps I am not understanding the > whole story. Wanna see the compiler errors I get without my crazy class? |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jul 15 05:59AM -0700 On Monday, July 15, 2019 at 7:19:24 AM UTC-4, Frederick Gotham wrote: > > That sounds hard to believe so perhaps I am not understanding the > > whole story. > Wanna see the compiler errors I get without my crazy class? Yes, along with the code that triggered those errors and, for every class relevant to those error messages, enough of the definition to understand what those messages mean. Note: if you weren't sure what those messages meant, be VERY cautious about dropping something just because you think it's not relevant. |
red floyd <dont.bother@its.invalid>: Jul 12 10:44AM -0700 On 7/12/2019 7:17 AM, Scott Lurndal wrote: > register could contain data or an address. > For that matter, modern x86_64 is actually no so bad (the biggest > warts with the original 8086/80286 were related to segmented memory). Z8000, anyone? Similar to 68K, but the registers were all general, no differentiation. Z8000 was 16 bit registers, but could be subdivided into upper/lower half for bytes, and combined with an adjacent register for 32-bit registers (e.g. RR0 was R0 and R1 combined). Z80000 was the 32-bit version, doubled the number of registers, and allowed 64-bit "quad" registers. |
scott@slp53.sl.home (Scott Lurndal): Jul 12 08:00PM >number of bytes in an instruction pipeline are holding rex, data, >address, escape and other prefix bytes that would otherwise be more >compactly contained within the instruction. I can't speak for x86, but the AArch instruction encoding is baroque specifically to make the hardware design easier. Given the microcoded nature of the x86 processor and given that the majority of frequently used instructions have a single-cycle latency, I don't see that the complexity of the instruction set has impacted performance. It does, to a certain extent, impact the area required, but the vast majority of area on a processor chip is devoted to L1 and L2 caches. |
scott@slp53.sl.home (Scott Lurndal): Jul 12 06:35PM >(actually, make that three, for those of us who write processor >simulators for a living, we need to decode (and execute) the instruction >set). Ah, make that four - our hypervisor did have to simulate a handful of instructions when trapping guest accesses to virtual PCI I/O devices. e.g. // Decode the instruction. c_instr_iterator iter((void *)instr, rip); len = get_operand_length(&iter); // Interpret the instruction. switch (iter.get_opcode()) { case 0xb60f: // movzb mem, reg value = trace->mem_read(addr, BYTE); value >>= ((addr & 0x3) * BITS_PER_BYTE); value &= (1UL << 8 * BYTE) - 1; set_reg_value(regs, iter.get_modRM(REG), value, len); break; case 0xb70f: // movzw mem, reg value = trace->mem_read(addr, WORD); value >>= ((addr & 0x3) * BITS_PER_BYTE); value &= (1UL << 8 * WORD) - 1; set_reg_value(regs, iter.get_modRM(REG), value, len); break; ...etc for most other instructions that access memory. But it is still very rare for anyone else to care about the instruction encoding. |
David Brown <david.brown@hesbynett.no>: Jul 12 05:21PM +0200 On 12/07/2019 16:17, Scott Lurndal wrote: > Personally, I find the PDP-11 to be a nice design. 68000 had > differentiated registers (A0-A6, D0-D7) while on the PDP-11 any > register could contain data or an address. I haven't used the PDP-11, but I have used the msp430 microcontrollers which have a very similar ISA. And they too are very pleasant cpus to work with in assembly language or C. > For that matter, modern x86_64 is actually no so bad (the biggest > warts with the original 8086/80286 were related to segmented memory). Certainly it seems to be a lot better than older x86 - more registers and fewer register specific instructions helps. |
Szyk Cech <szykcech@spoko.pl>: Jul 12 05:35PM +0200 W dniu 11.07.2019 o 07:16, Öö Tiib pisze: > So you want to use module of Qt for writing QML applications but > you don't want to write QML applications? Nonsense. Programmer can't be so lame to tell this! You talk nonsense! Qt Quick classes were written in C++ and exposed to QML exclusively. So there is no technical reasons to not use it in pure C++ apps. Only the Qt vendor lock politics prohibit programmers from this! If you don't know about Qt history, architecture, and politics - don't write. Otherwise you appear as ignorant (which is soft term mean: stupid). |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment