views:

121

answers:

7
+1  Q: 

wchar_t pointer

What's wrong with this:

wchar_t * t = new wchar_t;

t = "Tony";

I thought I could use a wchar_t pointer as a string...

A: 

this is completely wrong. There's no need to allocate two bytes, make t to point to them, and then overwrite the pointer t leaking the lost memory forever.

Also, "Tony" has a different type. Use:

wchar_t *t = L"Tony";

IMHO better don't use wchars at all - See http://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful

Pavel Radzivilovsky
Probably a typo but wchar_t t = ... should be wchar_t *t = ...
Niki Yoshiuchi
fixed, thx. a tpyo..
Pavel Radzivilovsky
Also a wchar_t isn't necessarily two bytes. In the version of gcc I'm using a wchar_t is 4 bytes, and the standard says it's compiler specific. It can even be a single byte.
Niki Yoshiuchi
+8  A: 

Your code has two issues.

First, "Tony" is a pointer to a string of char's. L"Tony" is the appropriate wide string.

Second, you allocate a single wchar_t via new, then immediately lose track of it by reassigning the pointer to Tony. This results in a memory leak.

Michael
To expand on Michael's explanation, the correct syntax would be `wchar_t* t = L"Tony";`. This would declare a pointer and initialize it to point to the static (wide) string "Tony".
bta
The syntax Should actually be `wchar_t const* t = L"Tony";`. To see why, consider the statement `*(t+1) = L'i';`
MSalters
+5  A: 

What this does is first assign a pointer to a newly allocated wchar_t into t, and then try to assign a non-wide string into t.

Can you use std::wstring instead? That will handle all your memory management needs for you.

Mark B
wstring only exists in MSVC. It's not standard.
Pavel Radzivilovsky
@Pavel: That is very wrong. wstring is `typedef`'ed as a `basic_string<wchar_t>` and exists on *every* compliant C++ system/toolchain.
rubenvb
@Pavel: §21.2/2: "The header `<string>` also defines two specific template classes `string` and `wstring` and their special traits."
GMan
@Pavel Radzivilovsky wstring is standard (at least the cppreference says it is http://www.cppreference.com/wiki/string/start and all wstring wstringstream,wcin,... classes work with g++) the only thing here could be microsoft not implementing the c++ standard.
josefx
They did implement a fairly-standard `wstring` back in '98, in their VC6 release. More recent versions have removed some minor non-compliances in their `wstring` implementation. (The most important was that `wchar_t` was a typdef in VC6)
MSalters
A: 

you can, its just that "Tony" is a hardcoded string, and they're ANSI by default in most editors/compilers. If you want to tell the editor you're typing in a Unicode string, then prefix it with L, e.g. t = L"Tony".

You have other problems with your code, your allocation is allocating a single Unicode character (2 bytes), then you're trying to point the original variable to the constant string, thus leaking those 2 bytes.

If you want to create a buffer of Unicode data and place data into it, you want to do:

wchar_t* t = new wchar_t[500];
wcscpy(t, "Tony");
gbjbaanb
The size of a wchar_t is compiler specific and may be as small as 1 byte and as large as 4.
Niki Yoshiuchi
A: 

A couple of things:

If you need a pointer to an array:

const wchar_t (*arr)[5] = "Tony";

Remember that you'll need to keep track of the memory and call delete[] when you're done with it (or the wchar_t pointer will be going out of scope)

It would be a lot better if you'd just use std::string or std::wstring from the <string> header, they are much better for every reason.

rubenvb
Right, my bad... I never use these things or at least avoid them as much as possible :)
rubenvb
What you have there is an array of pointers. That's plain wrong.
sbi
@sbi: Actually, `arr` is a pointer to an array of 5 `const wchar_t` objects, but you are right that the initialization of `arr` is incorrect. It could be `const wchar_t (*arr)[5] = `.
Daniel Trebbien
You wouldn't want to call `delete[]` on `arr` because `arr` was not obtained via `new[]`.
Daniel Trebbien
I should think better before posting :s
rubenvb
Well, so should I. `:(`
sbi
+3  A: 

A pointer just points to a single value. This is important.

All you've done is allocated room for a single wchar_t, and point at it. Then you try to set the pointer to point at a string (remember, just at the first character), but the string type is incorrect.

What you have is a string of char, it "should" be L"Tony". But all you're doing here is leaking your previous memory allocation because the pointer holds a new value.

Rather you want to allocate enough room to hold the entire string, then copy the string into that allocated memory. This is terrible practice, though; never do anything that makes you need to explicitly free memory.

Just use std::wstring and move on. std::wstring t = L"Tony";. It handles all the details, and you don't need to worry about cleaning anything up.

GMan
IMO the most correct answer and, with using `std::wstring`, the best advice.
sbi
@sbi: Why thank you. :)
GMan
Excellent answer.
Daniel Trebbien
+3  A: 

Since you are a C# developer I will point out a few things c++ does different.

This allocates a new wchar_t and assigns it to t

wchar_t* t = new wchar_t

This is an array of constant char

"Tony" 

To get a constant wchar_t array prefix it with L

L"Tony"

This reasigns t to point to the constant L"Tony" instead of your old wchar_t and causes a memory leak since your wchar_t will never be released.

t = L"Tony"

This creates a string of wide chars (wchar_t) to hold a copy of L"Tony"

std::wstring t = L"Tony"

I think the last line is what you want. If you need access to the wchar_t pointer use t.c_str(). Note that c++ strings are mutable and are copied on each assignment.

The c way to do this would be

const wchar_t* t = L"Tony"

This does not create a copy and only assigns the pointer to point to the const wchar array

josefx