- Why c++ executes destructors of moved objects? - 21 Updates
- reinterpret_cast question (with correction!) - 4 Updates
Melzzzzz <mel@zzzzz.com>: Aug 10 01:27AM +0200 On Wed, 10 Aug 2016 00:20:43 +0100 > It is not really a problem to write classes this way. I am relaxed > about it. You very soon get used to it. Well, I'll live with it, just I am spoiled by Rust ;) |
red floyd <no.spam@its.invalid>: Aug 09 04:29PM -0700 On 8/9/2016 2:29 PM, Melzzzzz wrote: > destructor > [bmaxa@maxa-pc examples]$ > Is this defect, and what is point of moving around, if not? No, it's not a defect. You have * A constructed * B move constructed * B destructed * A destructed |
red floyd <no.spam@its.invalid>: Aug 09 04:31PM -0700 Never mind. I thought he was asking why the move constructor destroyed the moved object. |
"Öö Tiib" <ootiib@hot.ee>: Aug 09 04:49PM -0700 On Wednesday, 10 August 2016 01:57:53 UTC+3, Melzzzzz wrote: > > wise to design the class so that it can still be assigned to after the > > move. > It looks to me like half baked solution. BINGO! C++ is never fully baked solution. It is always just a tool-set and materials from what *you* can make the stove, dough and other things that you may be think you need for baking and have your best baked solution. Additionally it is assumed that you are pyromaniac, aren't you? So there is always some bear traps with TNT in every component of C++. |
Paavo Helde <myfirstname@osa.pri.ee>: Aug 10 02:59AM +0300 On 10.08.2016 1:56, Melzzzzz wrote: > That also means that there is unnecessary code for maintaining state > and also run time errors in case that object is moved twice... > (what one should do if constructing from already moved object?) As the object is still in a valid state, it can be freely moved from again, and one typically gets a copy of the empty/sentinel value (an empty string, for example). > moved object is used after move (except assignment). Also compiler > doesn't call destructors on moved objects so there is no need to worry > about that. So the house-keeping is essentially done by Rust compiler. This is another ideology which might work as well. It's just not in the spirit of C++ (as it seems to take away some ways to shoot one's legs off ;-) (together with some loss of control and flexibility)). Just for curiosity, what does Rust do when an object is moved-from in one code branch and not in another? A compiler error? Cheers Paavo |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Aug 09 05:19PM -0700 What does this syntax mean? A(A && moved) { /* code here */ } I've never seen it before. Best regards, Rick C. Hodgin |
Melzzzzz <mel@zzzzz.com>: Aug 10 02:37AM +0200 On Wed, 10 Aug 2016 02:59:10 +0300 > Just for curiosity, what does Rust do when an object is moved-from in > one code branch and not in another? A compiler error? I don't understand? In Rust everything is moved by default. That is if compiler finds that value is moved it always complaints if there is other place where value is used. In such cases, one should make copy of value , which is in Rust implementing Clone trait and providing clone function. Of course, there is also Copy trait (derived from Clone) if calling clone is not convenient. One is not required to implement Clone as there is #[derive(Clone)] directive for automatic derivation, inspired by Haskell. |
Nobody <nobody@nowhere.invalid>: Aug 10 03:48AM +0100 On Tue, 09 Aug 2016 17:19:21 -0700, Rick C. Hodgin wrote: > /* code here */ > } > I've never seen it before. It's a move constructor. A&& is an rvalue reference, introduced in C++11. Basically, move constructors allow you to avoid deep-copying an object that's about to be destroyed or overwritten. The move constructor can just steal any dynamically-allocated data from "moved" rather than copying it. |
woodbrian77@gmail.com: Aug 09 09:03PM -0700 On Tuesday, August 9, 2016 at 9:48:48 PM UTC-5, Nobody wrote: > Basically, move constructors allow you to avoid deep-copying an object > that's about to be destroyed or overwritten. The move constructor can > just steal any dynamically-allocated data from "moved" rather than copying I'd say "adopt" rather than "just steal". "Adopt" is shorter and the word "just" before "steal" makes stealing sound like a small thing. "There are four character types among people. One who says, 'What's mine is mine and what's yours is yours' is of average character, and some say, this is the character of Sodom. [One who says] 'What's mine is yours and what's yours is mine' is unlearned (lit., [of] the people of the land). [One who says] 'What's mine is yours and what's yours is yours' is pious. [One who says] 'What's yours is mine and what's mine is mine' is wicked." http://torah.org/learning/pirkei-avos-chapter5-13/ > it. Brian Ebenezer Enterprises http://webEbenezer.net |
"Öö Tiib" <ootiib@hot.ee>: Aug 10 12:32AM -0700 On Wednesday, 10 August 2016 03:37:32 UTC+3, Melzzzzz wrote: > I don't understand? In Rust everything is moved by default. That is if > compiler finds that value is moved it always complaints if there is > other place where value is used. It is possible to make code where proof that moved value is not used can take very long time. Compiler can't hang on such code. So there must be situation when it is uncertain. Now at that point it is interesting if Rust's compiler does reject code when it can prove that moved value is used or it does reject code when it can not prove that used value is not moved or you don't know what it does. |
David Brown <david.brown@hesbynett.no>: Aug 10 10:14AM +0200 On 10/08/16 02:19, Rick C. Hodgin wrote: > /* code here */ > } > I've never seen it before. It is almost always written "A&& " rather than "A && ", just as "A&" is used for a lvalue reference (the kind C++ has always supported) rather than writing "A &". I certainly thought it looked strange with the extra space. rvalue references are new to C++11. They let you get a reference to something that is anonymous or temporary, and let you "move" data around rather than copying it. In particular, if you have an object that owns some data or resource, and you "move" it somewhere else (such as into a function), then you move ownership - the called function becomes responsible for the object. <http://thbecker.net/articles/rvalue_references/section_01.html> <http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html> <https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers> rvalue references are somewhat hard to grasp - they are one of the hardest new features of C++11. But they can make a big difference to the efficiency of some kinds of code, and are therefore useful when making class libraries. However, if you are just using classes, you can use something like the unique_ptr<T> classes without understanding the "magic" behind the scenes that make them work. |
David Brown <david.brown@hesbynett.no>: Aug 10 10:24AM +0200 >> that's about to be destroyed or overwritten. The move constructor can >> just steal any dynamically-allocated data from "moved" rather than copying > I'd say "adopt" rather than "just steal". "Adopt" is a better word for this than "steal", but that is because during a "move" the source actively gives the data to the destination, and the destination adopts responsibility for the data and resources. Trying to apply human morality to programming terms makes it look like you don't understand morality, and you don't understand programming. /Programmers/ can be moral or amoral - programs cannot. |
Melzzzzz <mel@zzzzz.com>: Aug 10 11:04AM +0200 On Wed, 10 Aug 2016 00:32:42 -0700 (PDT) > interesting if Rust's compiler does reject code when it can prove > that moved value is used or it does reject code when it can not prove > that used value is not moved or you don't know what it does. I think that Rust compiler just complains if it sees any code path where value is moved regardless. |
"Öö Tiib" <ootiib@hot.ee>: Aug 10 03:08AM -0700 On Wednesday, 10 August 2016 12:04:40 UTC+3, Melzzzzz wrote: > > that used value is not moved or you don't know what it does. > I think that Rust compiler just complains if it sees any code path > where value is moved regardless. So you think that following code will be rejected by Rust? I write just pseudo-code, I don't know Rust. Comment "..." means code that does not deal with neither 'condition' nor 'variable': if ( condition ) { // ... move( variable ); // ... } // ... unless ( condition ) { // ... use( variable ); // <- we can't reach that with moved 'variable' // ... } |
"Öö Tiib" <ootiib@hot.ee>: Aug 10 03:11AM -0700 On Wednesday, 10 August 2016 11:24:42 UTC+3, David Brown wrote: > Trying to apply human morality to programming terms makes it look like > you don't understand morality, and you don't understand programming. > /Programmers/ can be moral or amoral - programs cannot. That can be viewed as existential risk for humankind. Stephen Hawking talks about it: http://www.dailymail.co.uk/sciencetech/article-3406751/Hawking-Threats-human-survival-likely-new-science.html Some even research that risk: http://cser.org/research/current-projects/ IOW ... depends how to look at if ... if it is a problem, or if it is misunderstanding. |
Melzzzzz <mel@zzzzz.com>: Aug 10 12:24PM +0200 On Wed, 10 Aug 2016 03:08:28 -0700 (PDT) > 'variable' > // ... > } [bmaxa@maxa-pc examples]$ cat moved.rs struct A; impl Drop for A{ fn drop(&mut self) { println!("destructor"); } } fn main() { let a = A; if false { let b = a; } else { } if false { let c = a; } } [bmaxa@maxa-pc examples]$ rustc moved.rs error[E0382]: use of moved value: `a` --> moved.rs:15:13 | 11 | let b = a; | - value moved here ... 15 | let c = a; | ^ value used here after move | = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait error: aborting due to previous error |
Daniel <danielaparker@gmail.com>: Aug 10 06:47AM -0700 On Wednesday, August 10, 2016 at 4:24:42 AM UTC-4, David Brown wrote: > /Programmers/ can be moral or amoral - programs cannot. Sure they can. A deep learning program could be taught to be moral, with Old Testament training sets. After training and testing, it could be set to control sensors that activated weapons systems. Daniel 10 When thou comest nigh unto a city to fight against it, then proclaim peace unto it.... 13 And when the Lord thy God hath delivered it into thine hands, thou shalt smite every male thereof with the edge of the sword: 14 But the women, and the little ones, and the cattle, and all that is in the city, even all the spoil thereof, shalt thou take unto thyself; and thou shalt eat the spoil of thine enemies, which the Lord thy God hath given thee. 15 Thus shalt thou do unto all the cities which are very far off from thee, which are not of the cities of these nations. 16 But of the cities of these people, which the Lord thy God doth give thee for an inheritance, thou shalt save alive nothing that breatheth: Deuteronomy 20:10-16 15 And Moses said unto them, Have ye saved all the women alive? 16 Behold, these caused the children of Israel, through the counsel of Balaam, to commit trespass against the Lord in the matter of Peor, and there was a plague among the congregation of the Lord. 17 Now therefore kill every male among the little ones, and kill every woman that hath known man by lying with him. 18 But all the women children, that have not known a man by lying with him, keep alive for yourselves. Numbers 31:15-18 |
Melzzzzz <mel@zzzzz.com>: Aug 10 03:49PM +0200 On Wed, 10 Aug 2016 06:47:19 -0700 (PDT) > Sure they can. A deep learning program could be taught to be moral, > with Old Testament training sets. After training and testing, it > could be set to control sensors that activated weapons systems. Could it be said that malware is amoral? |
"Adam C. Emerson" <azure@fox.blue>: Aug 10 05:40PM > clone is not convenient. > One is not required to implement Clone as there is #[derive(Clone)] > directive for automatic derivation, inspired by Haskell. I think the problem you're having is that you assume that C++ 'move' construction and assignment are analogous to Rust's notion of ownership. Rust's ownership is a compile time property managing lifetimes and keeping track of when data can be safely disposed of. In C++, 'move' isn't really an operation. You have a special kind of reference (an rvalue reference) and you can overload functions, including the constructor and assignment operators, to behave differently when they receive an rvalue reference. The rvalue overload overloads of the constructor and assignment operators are traditionally called 'move' constructors and 'move' assignment operators. Both are allowed to do whatever you want, though if you write some weird move constructor you will probably have great sorrow and heaps of infelicity when you go to use your class with the standard library or other code. To be useful and integrate well with the rest of the language, the move constructor MUST leave the 'moved-from' object in a valid state. It doesn't have to be 'empty' it just has to be a valid object. You will generally only bother writing a move constructor if you can get some use out of it. So, say, if your class contains a pointer to allocated memory, you might copy the pointer to the new object and null it in the old (moved-from) object. C++'s idea of movement makes no sense at all in Rust, since in C++ you have to manage your own memory and manage lifetimes on your own and all that other stuff. So, while they might not be what you're used to or what would make sense in other languages, move semantics make sense within the general shape of C++ as a language and as a set of practices (like RAII). |
Melzzzzz <mel@zzzzz.com>: Aug 10 08:08PM +0200 On Wed, 10 Aug 2016 17:40:29 -0000 (UTC) > C++'s idea of movement makes no sense at all in Rust, since in C++ you > have to manage your own memory and manage lifetimes on your own and > all that other stuff. Rust is same as C++ regarding memory management. It's just that unique_ptr is build into language... Box::new(Type) allocates on heap and returns unique_ptr. There are also structs like Rc which are actually shared_ptr. Resources are managed by RAII. Actually Rust in the beginning had GC but that was later ditched from language, I guess because of performance reasons... |
Melzzzzz <mel@zzzzz.com>: Aug 10 08:15PM +0200 On Wed, 10 Aug 2016 20:08:28 +0200 > Box::new(Type) allocates on heap No, Box::new(data), as it is just like any other function... |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Aug 10 12:23AM +0100 On 10/08/2016 00:02, Daniel wrote: >> It was necessary to do that to ensure that a key cannot be changed once >> added to the binary search tree. > No. That's an interface issue, not an implementation issue. It is both. > There is no problem if value_type is defined as a type having a key() accessor > that is non-modifying. You cannot allow the key to be changed by allowing access to it hence it must be const. > might change the key. If it's a perverse class implementer you're worried > about, well, he could always remove a tree node and replace it with a new one > with a different key, const key or not. You don't get it: if a key in a binary search tree is changed the tree can become corrupt and invalid. > Anyway, this is, while regrettable, unable to be changed. It isn't regrettable as it is the correct design. /Flibble |
Daniel <danielaparker@gmail.com>: Aug 09 05:03PM -0700 On Tuesday, August 9, 2016 at 7:23:42 PM UTC-4, Mr Flibble wrote: > if a key in a binary search tree is changed the tree > can become corrupt and invalid. Obviously. Nobody has suggested otherwise. In fact, that's true of associative containers generally. > It isn't regrettable as it is the correct design. What you're saying is that the standard requirement for associate containers, that they _must_ store key value pairs in std::pair<const Key,mapped_typed> value types, and allow no other internal physical representation, is the correct design. That doesn't work for btrees, where value types have to be shuffled between blocks when re-balancing, and it doesn't work for b+ trees, where keys and values are stored separately, and it doesn't work for sequences of key value pairs. All of these associative data structures have the logical requirement that the key doesn't change, but a whole class of them can't use std::pair<const Key,mapped_typed> for physical storage. The interface for associative containers shouldn't dictate that they must. The fact that it does is regrettable, because a whole class of associative containers that have desirable characteristics can't participate in generic algorithms. And it was unnecessary. Best regards, Daniel |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Aug 09 07:13PM -0500 > regrettable, because a whole class of associative containers that have > desirable characteristics can't participate in generic algorithms. > And it was unnecessary. It was not unnecessary for map as it is the correct design for map. /Flibble |
Daniel <danielaparker@gmail.com>: Aug 09 06:00PM -0700 On Tuesday, August 9, 2016 at 8:13:24 PM UTC-4, Mr Flibble wrote: > It was not unnecessary for map as it is the correct design for map. I don't think so :-) iterator and const_iterator are not required to be particular types, just types that have certain properties. Similarly, there was no reason to require that value_type be a particular type (std::pair<const key_type,mapped_type>), as with the iterator types, it would have been enough to specify that it have certain properties (an accessor for a key, an accessor and a modifier for a value.) That would have allowed a larger class of map-like containers to be introduced and be used interchangeably, much as it is already possible to use a wide class of sequence containers interchangeably. Best regards, Daniel |
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