Talk:Destructor (computer programming)
This article is rated C-class on Wikipedia's content assessment scale. It is of interest to the following WikiProjects: | ||||||||||||||||||
|
Return value?
[edit]- Section added. —Nils von Barth (nbarth) (talk) 13:46, 4 May 2014 (UTC)
Which language returns value from a dtor function? (as written in the introduction) I kow abt c++. It does not return any value from dtor fuction call.
PHP5
[edit]PHP5 introduces destructors. Probably should be covered here. I came here hoping someone would be ahead of me in sorting out: is there (as in C++) a guarantee that the destructor runs promptly when a statically declared object passes out of scope, or might it run at some later time? There are techniques in C++ programming that rely on this aspect of destructors, I'm wondering whether they will work in PHP5.- Jmabel | Talk 17:33, 21 February 2008 (UTC)
- This article would suggest that it works, starting with PHP 5.2, but I don't know how definitive it is. - Jmabel | Talk 17:40, 21 February 2008 (UTC)
Merging virtual destructor description to Examples -> C++ section?
[edit]AFAIK, only C++ really has virtual dtors, so wouldn't it make more sense to merge that with the Examples -> C++ section? Not to mention that the virtual dtor section really only references C++ anyway. Thoughts?
Sebastian Garth (talk) 17:46, 19 September 2009 (UTC)
I think that the C++ example is too difficult for explaining the concept of destructor. I seriously doubt the explanatory value of it. I recommend a much simpler example like this:
class Board {
public:
Board(int w_, int h_) // Constructor of Board
: w(w_) // Save the w_ parameter to the w member variable
, h(h_) // Like the above
, cells(new Cell[w*h]) // Allocate memory for board cells, w*h pieces.
{
// ... some program
}
// ... Some methods
~Board() // Destructor of Board
{
delete[] cells; // Free the memory
}
private:
int w,h; // width and height
Cell *cells; // cells. Cell is a type which is not explained in this example
};
// ...
int main()
{
Board b(8,8); // <--- Constructor for b is called (Board::Board()), created as automatic variable
Board *x = new Board(8,8); // <--- Constructor for x is called (Board::Board()), allocated manually
// ...
delete x; // <--- Destructor for x is called (Borad::~Board()), destroyed manually
// ...
return 0;
} // <--- Destructor for b is called (Borad::~Board()), destroyed automatically when goes out of scope
by Notinlist (talk) 04:14, 3 May 2010 (UTC)
- For the average C++ programmer, I think the existing example is fairly straightforward. Also, the code you posted is frankly not a good example of best practices, eg: using signed integers without sanity checks, improper usage of RAII, inconsistent naming conventions, no encapsulation, superficial objectification, etc... Sebastian Garth (talk) 06:15, 3 May 2010 (UTC)
- I told that a "I recommend a much simpler example like this:", I haven't told that it is final and bulletproof solution. Yes, more checks needed. The RAII usage is not improper. The naming convention is not inconsistent. Maybe it is not your style but it does not have internal inconsistency. What do you mean by no encapsulation? Where do you see the superficial objectification? (Which may be there but you missed to give details.) And I don't like when people are talking to me "frankly". You may be right on many points, please tell them not "frankly"! Notinlist (talk) 13:20, 4 May 2010 (UTC)
- There's no need to take offense - the code you posted was broken and sloppy, so I called you out on it. Maybe I should've elaborated a bit more on the problems that I noticed? Okay, well, here goes:
- 1) The rule of RAII is that all dynamic allocations (and other resources) are strictly controlled by "smart-pointers". Failing to do so creates all sorts of problems, relating to copy-construction, exceptions, scope, etc. So the bottom line is that *all* examples using allocation *must* use RAII. Teaching people otherwise is just irresponsible, IMO.
- Are we talking about "Board *x = new Board(8,8);"? That was for the example's sake. Yes I know that this is not RAII. That one was intentional. I believed that you know that this is intentional. I wanted to set two examples. One: When destructor is called by leaving the scope. Two: When destructor is called when "delete" is explicitly used. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- No, I'm saying "operator new" should never be assigned to a raw pointer (unless you're designing a smart-pointer class, of course).Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- RAII does not mean "operator new should never be assigned to a raw pointer". Smart pointers - as anything in the World - can be overused. Some say that it is the safe choice to put them everywhere, others say it gives unnecessary complexity most of the time and produces awkward situations and performance issues many times. But after all, RAII is not equal to "smart pointers everywhere" so the "improper usage of RAII" cannot be stated based on that. Notinlist (talk) 02:17, 5 May 2010 (UTC)
- No, I'm saying "operator new" should never be assigned to a raw pointer (unless you're designing a smart-pointer class, of course).Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- Are we talking about "Board *x = new Board(8,8);"? That was for the example's sake. Yes I know that this is not RAII. That one was intentional. I believed that you know that this is intentional. I wanted to set two examples. One: When destructor is called by leaving the scope. Two: When destructor is called when "delete" is explicitly used. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- 2) Naming conventions should be consistent. The example you posted uses a mix of single-letter and fully spelled out variable names. So pick one style and stick with it.Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- The usage of "w" and "h" for width and height is - one can almost say - universal. There is no one-letter name for "cells", so I called it "cells". Notinlist (talk) 19:10, 4 May 2010 (UTC)
- Well, it sure seems inconsistent to me...Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- The usage of "w" and "h" for width and height is - one can almost say - universal. There is no one-letter name for "cells", so I called it "cells". Notinlist (talk) 19:10, 4 May 2010 (UTC)
- 3) Encapsulation means not exposing the internals of an object in such a way that the stability of the data structure can be easily compromised. For instance, with the object that you gave as an example, the user could simply increment the "height" variable, and now the object is an unstable state. So, unless you can guarantee that the modification of a member variable won't do such a thing, you need to provide a set of accessors.
- ... simply could increment the height variable ...? Which example do you look at? All data members are private! The "set of accessors" can be imagined at the "// ... Some methods" section. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- Ah, right. Yes, an allusion to the methods probably would have been sufficient.Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- ... simply could increment the height variable ...? Which example do you look at? All data members are private! The "set of accessors" can be imagined at the "// ... Some methods" section. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- 4) Superficial objectification arises from a misguided belief that "everything is an object", or OOP for the sake of OOP. Moreover, when these objects don't even provide a true interface, you essentially end up with glorified C-style "structs". For example, the object you provided can't really be accessed like a board, eg: myBoard[ row ][ column] = 0xff, so what is the point, really?
- You are talking about things that are not there. I don't want to go to details on that, because you are basically right, but not on the viewpoint you explained. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- 5) All objects should have safe copy construction semantics. The example you posted does not, as the assignment of one "board" to another would simply cause the member "cells" to be copied by value, with disasterous effects. Ironically, had you used RAII (eg: std::vector instead of "raw" pointers), the copy-constructor wouldn't even need to have been written!
- True. Agree. I missed that one. But this bad effect would not be in the final version if there were one ever. I don't release code with such errors. Maybe to a discussion board. ;-) Notinlist (talk) 19:10, 4 May 2010 (UTC)
- 6) Instead of using a signed integer, with checks, you could simply use "std::size_t", which is guaranteed to be unsigned.
- Agreed. Even for the first time. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- Sebastian Garth (talk) 16:39, 4 May 2010 (UTC)
- Back to the topic... My point was that the example could be about something that is not for the technology itself. Examples have better explanatory values where they are somehow connected to the real world (if it is possible of course). We are explaining the "destructor" here. The explanation should be based on simpler things, not more difficult things (like the concept of dynamic pointer, operator overloading, copy constructor, disabling copy semantics, etc ...). There is no audience for the current example. If you don't know what a destructor is you will surely not learn it from that code snippet. Notinlist (talk) 13:20, 4 May 2010 (UTC)
- I see your point now. Well, perhaps we could just provide an example that prints from the destructor, or something?Sebastian Garth (talk) 16:39, 4 May 2010 (UTC)
- My previous example was too artificial as Sebastian pointed out, but I still believe in simplicity, so I recommend the following example code for the article. I think it is better because it uses as few other features as possible, so it helps keeping the focus on the destructor.
#include <cstring>
class MyString
{
public:
MyString(const char *charArray) // Constructor
{
len = strlen(charArray); // Store length
pData = new char[len+1]; // Allocate memory
strcpy(pData,charArray); // Copy data from the parameter
}
// Place useful methods here...
~MyString() // Destructor
{
delete[] pData; // deallocate memory when destoyed
}
private:
size_t len; // data member for length
char *pData; // data member for characters
};
int main()
{
MyString s("This is a L'art pour L'art string."); // 's' is created here
// Place useful program here...
return 0;
} // 's' is destroyed automatically here, the destructor will be executed
- Note: This is not a production code, but a teaching example. Notinlist (talk) 15:38, 4 May 2010 (UTC)
- Nope, still broken. Refer to the issues outlined above.Sebastian Garth (talk) 16:39, 4 May 2010 (UTC)
- Refer to the answers of the issues outlined above. :-) Notinlist (talk) 19:10, 4 May 2010 (UTC)
- Nope, still broken. Refer to the issues outlined above.Sebastian Garth (talk) 16:39, 4 May 2010 (UTC)
Okay, well this should be simple enough:
#include <iostream>
using namespace std;
class example
{
public:
example( void )
{
print( "example()" );
}
virtual ~example( void )
{
print( "~example()" );
}
protected:
void print( string const& text )
{
cout << ( void* )this << " : " << text << endl;
}
// disable copy-constructor by making it private
private:
example( example const& )
{ }
};
int main( void )
{
example
array[ 3 ];
}
Would that be acceptable? Sebastian Garth (talk) 16:56, 4 May 2010 (UTC)
- Nice. (1) You disabled the copy constructor but not disabled the operator=(), don't see a point. (2) You wrote "using namespace std;" to the global scope which is not a good thing to teach. IMO. Notinlist (talk) 19:10, 4 May 2010 (UTC)
- (3) Creating virtual method table for a class that is not designed explicitly to be a base class for inherited classes is a waste of resources. Notinlist (talk) 20:03, 4 May 2010 (UTC)
- (4) Minor issue: You create and destroy an std::string unnecessarily. The print() method could simply accept "char const *". Notinlist (talk) 20:45, 4 May 2010 (UTC)
- (5) You included "iostream", but not included "string". It is an accident that it compiles on your system, since you are using the "std::string" class which is defined by the "string" include. Notinlist (talk) 20:51, 4 May 2010 (UTC)
- 1) True enough. 2) No, it just forces you to use the scope resolution operator, which you'd be using anyway if a potential conflict existed. Anyway, either way is fine with me. 3) No, it's a very good habit, actually. 4) Sorry, I don't use raw c-strings in my code. Ever. 5) Okay. Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
- (2) The usage of "using namespace ...;" in the global scope can have bad influences on the so called "unity builds" (which is not a new technique but the name is) which - in many cases - can reduce the build time by a factor of 10. Of course if you set up unity builds you have to take care about some name collisions with static variables which cannot be avoided forwardly. But hey. You can have one less problem. (4) Response and about the RAII: I like RAII but I don't like "one weapon for all". (3) It is also a "one weapon for all". Most of the time you don't need virtual destructor and the compiler warns you if you do. Notinlist (talk) 00:42, 5 May 2010 (UTC)
- 1) True enough. 2) No, it just forces you to use the scope resolution operator, which you'd be using anyway if a potential conflict existed. Anyway, either way is fine with me. 3) No, it's a very good habit, actually. 4) Sorry, I don't use raw c-strings in my code. Ever. 5) Okay. Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
Anyway, I've made changes to the example to address the concerns you've mentioned. Feel free to edit as necessary. Cheers. Sebastian Garth (talk) 22:37, 4 May 2010 (UTC)
Category theoretic notion of destructor
[edit]In the functional programming world the term destructor is sometimes used to mean "accessor" or "getter"; a Google search on "coalgebra destructor" gives several examples. I think this may warrant an explanatory link or something else to disambiguate, but am new to writing on wikipedia and don't know how to do that in keeping with the established style... 76.191.222.13 (talk) 03:35, 20 June 2010 (UTC)
- Correct, for example in OCaml we can destruct a (Cons a b) with a "match with" construct. But I don't know (yet) how to make a disambiguation either. --Libnoon (talk) 21:54, 25 July 2020 (UTC)