My understanding it that
LPSTR == char*
LPCSTR == const char*
Then you can throw your "T" in for Unicode conversion.
LPTSTR == LPWSTR or LPSTR
LPCTSTR == LPCWSTR or LPCSTR
I'm confused as to why these seem to be the most popular parameter types.
Typically I convert these types to a local CString in a function .. .then do
my work. Is this okay?
Thanks
> As I get back into MFC Coding, I'm reminded of the different data types
> that can be used for proper & efficient coding. Generally, I see
> functions that use LPTSTR & LPCTSTR. I'm wondering why the CString is not
> used as much as a parameter. If you pass "CString &", of course, it would
> be efficient as compared to passing the entire CString class.
The equivalence would be between LPCTSTR (i.e. 'const TCHAR *') and 'const
CString &'.
If you pass strings as read-only parameters to a function or method, I would
suggest to use LPCTSTR (i.e. 'const TCHAR *').
This way, you could pass both a string literal (without creating a new
temporary instance of CString) and a CString instance (in fact, there is an
implicit LPCTSTR conversion operator defined for the CString class).
Instead, if you want to pass modifyable string parameters, then I would
suggest to use 'CString &'.
If you return a string from a function or a method, I would suggest to just
pass an instance of CString.
e.g.
CString DoSomethingAndReturnString(
LPCTSTR psz // [input] const TCHAR *
CString & str // [input/output] reference to CString
);
> I'm confused as to why these seem to be the most popular parameter types.
You may want to read:
CString Argument Passing
http://msdn.microsoft.com/en-us/library/acttytz3(v=VS.80).aspx
Giovanni
That is correct. In context of MFC it is normally a major performance
fault to pass LPCTSTR around, because of e.g. this:
f(LPCTSTR param)
{
CString s(param); // Allocation!
// or similar use.
}
CString s = ...;
f(s);
Compare this to:
f(const CString& param)
{
CString s(param); // NO ALLOCATION, I win.
}
CString s = ...;
f(s);
In other words, one should use LPCTSTR only when sure that it will not
be converted to a CString, or somehow mixed with one, somewhere down
the line. And that's typically a tall order.
Goran.
You should never pass a parameter as non-const if it is never modified. The const
qualifier helps users identify if the string passed will be modified or not, and also the
compiler can produce slightly better code if a const is involved. But the documentation
value of const is far more important.
joe
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
HLS
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:#y804je8...@TK2MSFTNGP04.phx.gbl...
"Hector Santos" <sant...@gmail.com> wrote in message
news:hsgbb3$1epm$1...@news.ett.com.ua...
"Goran" <goran...@gmail.com> wrote in message
news:ca32288f-04d8-49e3...@n15g2000yqf.googlegroups.com...
>Whats the purpose of passing a "const CString &"?
>I will read the article.. thanks
>Any reason why you would prefer to use "const TCHAR" over "const CString &"
>in your function parameters?
****
I presume you mean "const TCHAR *", because "const TCHAR" is a simple scalar value which
is nominally sizeof(TCHAR) but is more likely 32 bits because of how parameters are
passed.
But a const TCHAR * can accept any constant string pointer, whereas "const CString &" can
only accept a CString. So if you pass _T("abc"), it will actually call the CString
constructor to create a CString object to pass in.
When I'm programming in MFC, I almost never have a data type OTHER than CString, so I tend
to use const CString & when I'm working within my native framework. I rarely have a raw
string literal in such cases, and in the extremely rare cases I do, I don't really care
about the constructor cost.
joe
Pretty much, yeah. At any rate, whenever you have a CString, and you
interact with a C API that has C string parameter, you'll either go
through directly through CString's "C string" conversion operators
(see operator PCXSTR in CString), or you will be forced to use one of
"buffer" routines for non-const params.
> Use CString, CString& or similarly with the "const" in front for Read Only.
Yes. It's not "Read only", it's more "input", really. Normally, you
really rarely want to use plain CString. You want that when you want
to pass it as an input (by value), and you want to modify it inside,
e.g. (warning: hugely contrived example):
void f(CString s)
{
if (whatever) s = val1; else s = val2;
someOtherFunc(s);
}
But that's just the same as:
void f(const CString& s)
{
CString local(s)
if (whatever) local = val1; else local = val2;
someOtherFunc(s);
}
(BTW, I bet you that you won't be able to see performance difference
in an optimized build between the two versions, and it's even possible
that compiler will compile the two to the exact same code).
As Joe said, using const for "input" parameters has a good
"documentation" value. I wonder if this will ever become a part of
typical coding guidelines for C and C++ (it should have, by now, but C
is an old language, and if it still isn't there for C code, so chances
of that ever happening are slim).
Goran.
> It really sounds like (for MFC) it's better to completely stay away from
> LPCTSTR & TCHAR.
> Use CString, CString& or similarly with the "const" in front for Read Only.
Yes, if you wish to ignore any performance lost due to the extra
overhead. But today's computers are fast so who cares? :)
But the other thing is issues may rear its ugly head when you are
passing it across boundaries, like between the exe and dlls.
For example, if you put your functions in a DLL, now they are highly
dependent on MFC being included in the DLL when it might have to be if
you are using passing a const string pointer and can work with it with
out needing the help from CString member functions.
You shouldn't have problems but you have to keep it in the back of
your mind for any heap related issues.
--
HLS
"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:7jgpu5h5t6vkdm4iu...@4ax.com...
Although probably a rare case, but in a multithreaded app, the
difference between CString and CString const & could be important.
e.g.
// Global resource:
CString csName("Albert");
// Thread 1:
...
DoSomething(csName); // line 1
...
// Thread 2:
...
csName = "Alex"; // line 2
...
Now consider if DoSomething is defined as
void DoSomething(CString csFriend)
{
...
cout << csFriend<< endl; // line 3
}
Now consider line1 begins execution, and the name "Albert" is copied
into the csFriend argument. Then control switches to thread 2 and
line 2 is executed. Then control goes back to thread 1 and line 3 is
executed. "Albert" will be printed.
If on the other hand DoSomething is defined with reference:
void DoSomething(CString const & csFriend)
{
...
cout << csFriend<< endl; // line 3
}
With the same serious of executions steps, "Alex" would be printed.
Depending on what you are trying to do, either one could be the
desired behavior.
"John H." <oldman_...@yahoo.com> wrote in message
news:2c44a0ec-d68b-4a3a...@s41g2000vba.googlegroups.com...
Well, that is true, but the problem is at a much lower level: code is
attempting to read/write a shared datum from multiple threads. That
does not work in a general case. Your example just muddies the waters
and tries to apply them to a CString&.
Goran.
It is not specific to C++.
Recently, I added a bunch of const declarations to a C- based library; we actually
uncovered some errors as a consequence! For example, there was a function that modified
an input string by writing into it, and this would have failed if a literal string was
passed in! (The result, because literal strings are placed in read-only memory, would
have been an access fault; and when I reported this, the response was "Yeah, we had some
tech support calls on that which we now understand")
joe
****
Anyone reading this code would realize that independent of the parameter type or the
copy-on-write semantics of CString, these is nothing right about the above code.
joe
****
>JCO wrote:
>
>> It really sounds like (for MFC) it's better to completely stay away from
>> LPCTSTR & TCHAR.
>> Use CString, CString& or similarly with the "const" in front for Read Only.
>
>
>Yes, if you wish to ignore any performance lost due to the extra
>overhead. But today's computers are fast so who cares? :)
****
No only that, but statistically the time is insignificant in nearly all cases. If this
were happening billions of times in an inner loop, the time might become statistically
significant.
****
>
>But the other thing is issues may rear its ugly head when you are
>passing it across boundaries, like between the exe and dlls.
>
>For example, if you put your functions in a DLL, now they are highly
>dependent on MFC being included in the DLL when it might have to be if
>you are using passing a const string pointer and can work with it with
>out needing the help from CString member functions.
****
I always assume a shared MFC DLL. The DLL runtime issue is one of the ugly secrets of C++
programming that Nobody Talks About, like the weird uncle at a family gathering. But as
soon as you have separate runtimes (static linking) all bets are off, not only for CString
but for all MFC structures. At that point, your problems are so serious that the impact
on CString is hardly noticeable; it is usually just the first victim of this problem.
****
>
>You shouldn't have problems but you have to keep it in the back of
>your mind for any heap related issues.
****
The same problem applies to the C runtime library with malloc and free. It is not unique
to C++ or MFC runtimes. A simple LPTSTR can fail just as badly.