<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: When to provide an empty destructor</title>
	<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/</link>
	<description>Boris Kolpackov's blog about software</description>
	<pubDate>Sat, 28 Oct 2023 17:47:34 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>

	<item>
		<title>By: Andrea</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1968</link>
		<author>Andrea</author>
		<pubDate>Mon, 09 Apr 2012 16:53:30 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1968</guid>
		<description>Ok, that makes sense now. Thanks for your clarification</description>
		<content:encoded><![CDATA[<p>Ok, that makes sense now. Thanks for your clarification</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1963</link>
		<author>Boris Kolpackov</author>
		<pubDate>Sun, 08 Apr 2012 08:22:22 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1963</guid>
		<description>Andrea, I am not comparing this to the case where the constructor calls are actually inlined. Instead, I am comparing it to the case were we provide our own, non-inline empty definition. In this case we will only have one instance of the function in one object file.</description>
		<content:encoded><![CDATA[<p>Andrea, I am not comparing this to the case where the constructor calls are actually inlined. Instead, I am comparing it to the case were we provide our own, non-inline empty definition. In this case we will only have one instance of the function in one object file.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrea</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1960</link>
		<author>Andrea</author>
		<pubDate>Fri, 06 Apr 2012 21:48:29 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1960</guid>
		<description>Boris, thanks for your explanation, but I think I'm still missing the point. As you say, for the first approach (which I agree: is what most of the mainstream compiler follow) "... then it instantiates the function in every translation unit that calls it ...". So why is this worse than the case where destructor calls were actually inlined? If destructor calls are really inlined, their code is expanded at _every_ call site, even in the same TU. In the first approach that you describe, they're expanded _once_ in every TU that calls it. Sorry to insist, but I think I'm missing what you're trying to say and since I'm really interested in this subject I'd reallly like to fully understand... 
Thanks,
Andrea.</description>
		<content:encoded><![CDATA[<p>Boris, thanks for your explanation, but I think I&#8217;m still missing the point. As you say, for the first approach (which I agree: is what most of the mainstream compiler follow) &#8220;&#8230; then it instantiates the function in every translation unit that calls it &#8230;&#8221;. So why is this worse than the case where destructor calls were actually inlined? If destructor calls are really inlined, their code is expanded at _every_ call site, even in the same TU. In the first approach that you describe, they&#8217;re expanded _once_ in every TU that calls it. Sorry to insist, but I think I&#8217;m missing what you&#8217;re trying to say and since I&#8217;m really interested in this subject I&#8217;d reallly like to fully understand&#8230;<br />
Thanks,<br />
Andrea.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1959</link>
		<author>Boris Kolpackov</author>
		<pubDate>Thu, 05 Apr 2012 10:41:12 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1959</guid>
		<description>Andrea, when a compiler decides not to inline a function, then it must "instantiate" this function as if it was non-inline. Or, in other words, as you said, the compiler will generate a call instruction to the function but this function that is being called must be created somehow (i.e., it must end up in the program text).

The way this is done depends on the implementation but generally there are two methods. If the compiler uses the first approach, then it instantiates the function in every translation unit that calls it and then weeds out duplicates at the link stage. With the second approach the compiler maintains some sort of a code database. When it compiles the first translation unit that calls our function, it instantiates this function and then adds it to this database. When another translation unit calls the same function, the compiler checks the database and sees that it has already been instantiated. Most popular C++ compilers (e.g., GCC, VC++) use the first method, which can lead to the situation I described.</description>
		<content:encoded><![CDATA[<p>Andrea, when a compiler decides not to inline a function, then it must &#8220;instantiate&#8221; this function as if it was non-inline. Or, in other words, as you said, the compiler will generate a call instruction to the function but this function that is being called must be created somehow (i.e., it must end up in the program text).</p>
<p>The way this is done depends on the implementation but generally there are two methods. If the compiler uses the first approach, then it instantiates the function in every translation unit that calls it and then weeds out duplicates at the link stage. With the second approach the compiler maintains some sort of a code database. When it compiles the first translation unit that calls our function, it instantiates this function and then adds it to this database. When another translation unit calls the same function, the compiler checks the database and sees that it has already been instantiated. Most popular C++ compilers (e.g., GCC, VC++) use the first method, which can lead to the situation I described.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrea</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1958</link>
		<author>Andrea</author>
		<pubDate>Thu, 05 Apr 2012 08:17:19 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1958</guid>
		<description>Nice and interesting article. I got a bit confused on the "Class with non-virtual destructor case". 
I'm perfectly on track when you say "...However, chances are good a C++ compiler will not actually inline calls to such a destructor due to its complexity.", but then the following: "In this case, object files corresponding to translation units that call such a destructor may end up containing multiple instances of the destructor" got me lost.
Isn't the case that if the compiler didn't inline calls to such destructors, the TU that call those destructors will only have a "call" (to be resolved by the linker) and not the whole copy of the destructor code in the generated object file? 
Am I mis-reading what you said?
Thanks,
Andrea.</description>
		<content:encoded><![CDATA[<p>Nice and interesting article. I got a bit confused on the &#8220;Class with non-virtual destructor case&#8221;.<br />
I&#8217;m perfectly on track when you say &#8220;&#8230;However, chances are good a C++ compiler will not actually inline calls to such a destructor due to its complexity.&#8221;, but then the following: &#8220;In this case, object files corresponding to translation units that call such a destructor may end up containing multiple instances of the destructor&#8221; got me lost.<br />
Isn&#8217;t the case that if the compiler didn&#8217;t inline calls to such destructors, the TU that call those destructors will only have a &#8220;call&#8221; (to be resolved by the linker) and not the whole copy of the destructor code in the generated object file?<br />
Am I mis-reading what you said?<br />
Thanks,<br />
Andrea.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1957</link>
		<author>Boris Kolpackov</author>
		<pubDate>Thu, 05 Apr 2012 06:56:39 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1957</guid>
		<description>Alex, it is not the shared_ptr declaration (actually, unique_ptr in my example) that the compiler cannot see. It is the object::impl declaration. C++ requires that the class should be complete when an instance of this class is freed using delete. In our case, if the object's destructor is inline, then when an instance of object is destroyed somewhere in user code, the inline destructor calls impl_'s destructor which in turn calls delete on a pointer to call object::impl, which is incomplete.</description>
		<content:encoded><![CDATA[<p>Alex, it is not the shared_ptr declaration (actually, unique_ptr in my example) that the compiler cannot see. It is the object::impl declaration. C++ requires that the class should be complete when an instance of this class is freed using delete. In our case, if the object&#8217;s destructor is inline, then when an instance of object is destroyed somewhere in user code, the inline destructor calls impl_&#8217;s destructor which in turn calls delete on a pointer to call object::impl, which is incomplete.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Alex Turner</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1956</link>
		<author>Alex Turner</author>
		<pubDate>Thu, 05 Apr 2012 06:27:08 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1956</guid>
		<description>I your pimpl example is a bit short on explanation. Why cannot the destructor see the shared_ptr declaration as that declaration is in the class declaration and so the template should be instantiated there?</description>
		<content:encoded><![CDATA[<p>I your pimpl example is a bit short on explanation. Why cannot the destructor see the shared_ptr declaration as that declaration is in the class declaration and so the template should be instantiated there?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1955</link>
		<author>Boris Kolpackov</author>
		<pubDate>Wed, 04 Apr 2012 20:15:28 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1955</guid>
		<description>Gregory, yes, that makes sense if a compiler-provided destructor is trivial (which means there is nothing to call).</description>
		<content:encoded><![CDATA[<p>Gregory, yes, that makes sense if a compiler-provided destructor is trivial (which means there is nothing to call).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gregory</title>
		<link>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1954</link>
		<author>Gregory</author>
		<pubDate>Wed, 04 Apr 2012 18:42:35 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/04/04/when-provide-empty-destructor/#comment-1954</guid>
		<description>I faced situations where MSVC++ would refuse to force inline a function returning an object with an empty destructor by value because it considered the object to be unwindable hence EH generated code went in the way of the optimizer

see http://stackoverflow.com/a/2322314/216063</description>
		<content:encoded><![CDATA[<p>I faced situations where MSVC++ would refuse to force inline a function returning an object with an empty destructor by value because it considered the object to be unwindable hence EH generated code went in the way of the optimizer</p>
<p>see <a href="http://stackoverflow.com/a/2322314/216063" rel="nofollow">http://stackoverflow.com/a/2322314/216063</a></p>
]]></content:encoded>
	</item>
</channel>
</rss>
