indranil banerjee writes
re: Virtual Function Behavior Between ISO C++ and C++/CLI Revisited
Thanks for the explanation. Rereading your earlier post and examples, it is quite clear that runtime resolution of virtuals is the same in both CLR and ISO C++.
However, now that I’ve understood the difference in virtual function resolution during object construction. I think will be even more hesitant to port ISO C++ code to C++/CLI. This is one more difference between the languages to be wary of. Is there anywhere on MSDN where a list of such difference will be maintained?
If I were in charge of a software project in which is the issue of porting ISO C++ code to C++/CLI came up [that is, publishing the type information within the CLR metadata for consumption across assemblies and languages], I would probably do the port incrementally, as follows:
- I would provide a C++/CLI wrapper to the ISO/C++ code, and would basically do the simplest thing possible: provide a one-to-one mapping of the public interface, in which each managed method is a simple stub to the equivalent native method. This would not be performant, but it would get me up and over the initial barrier. I would not manually do this, either, but invest my time in a tool that would auto-generate a mapping.
- Once this was available, I would begin to cache and synthesize methods such that crossing over between the managed/unmanaged barrier would be minimized. I would keep the original mapping so that the additional work is non-invasive, and then I would incrementally move certain critical pieces of the managed part from the initial mapping to the synthesized/cached interface. This would permit performance measure and tuning. I imagine this as being analogous to minimizing the communication over a data-base connection, doing as much as possible in memory, etc.
- Finally, once I had a handle on the hot spots within the C++/CLI wrapper, I would begin judiciously porting those portions of it that actually seem critical, and on moving this or that aspect of an application, be sure to profile the performance and be clear what has been gained and lost, etc.
This in part mirrors the early days of C++ usage with an existing C body of code, particularly when back in those days the performance overhead of C++ was a real concern to C programmers and their management.
As to your question about, is there anywhere on MSDN where such a list of differences will be maintained, the answer has to be the infamous yes and no. Yes, there should be a list maintained, ideally with examples that are not too trivial, and suggestions where possible for `best practices’. No, that will probably not be on MSDN but on a Visual C++/CLI web site that we are putting into place even as I write. And no, I don’t believe a list currently exists.
Finally, I believe virtual constructor calls within a constructor represents the 20% of the 80-20 pattern of usage, and so is not a real show-stopper. People that leverage this sort of hierarchical initialization and destruction tend to be the sophisticated user, I would imagine, and they would need to develop an alternative pattern under the Common Language Runtime Object Model.
Speaking of the 80-20 model, garbage collection resolves the 80% usage model of reclaiming heap memory automatically. What it fails to address is the 20% usage model of reclaiming other program resources such as a mutex or perhaps database connection. [This is the infamous non-deterministic finalization problem.] In the revised language, C++/CLI provides a deterministic finalization model through a destructor extension to the CLR Object Model. While this is a valuable mechanism for that 20%, I worry that C++ programmers, having internalized manually solving memory management through constructor/destructor pairs, will misuse this mechanism to perpetuate their non-managed habits and never give GC a real chance. This is one of the reasons I am not as much a champion of reproducing the native program within C++/CLI as others on the team.
Johan ericsson writes:
re: The Astonishing S”Literal” String Type
Not using the S is much better! I wonder, can we do the same for standard C++, ie get rid of the L. It could often be infered from the context.
Ie: the L shouldn’t really be necessary in the following statement:
const wchar_t * str = L”hi”;
The S was introduced into the original language design by analogy with the L [or so I presume]. Independent of the performance hit, the design is not bad. Another presumption I am going to make is that the original motivation of the L in C was to distinguish the size difference between literals, and of course that doesn’t transfer to the S type. The difference between a native and managed literal string is that the managed literal string is immutable. There is, of course, the reverse astonishment under the CLR of string manipulation generating potentially large numbers of string temporaries if we attempt to rewrite various characters of the string, such as turning “
So, why not change the need to have the L as well as the S? The short answer is because wide characters are not a part of C++/CLI but are a part of ISO C/C++, and that crosses over a boundary that we should not go [in my judgment] . If we introduce a set of differences in the shared common language, then (a) we run the risk of alienating those people involved in the standardization of that common language, and (b) we make it extremely difficult to identify a common subset that can be moved between the two languages. [I’m giving you this not to be persuasive but to give a sense of the arguments. You may not find this presentation convincing, but the main points should hold in a debate.]
Again, in my judgment [and