tags:

views:

59

answers:

1

I have an interface which is used like the following:

if (SUCCEEDED(pInterface->GetSize(&size))
{
    wchar_t tmp = new wchar_t[size];
    if (SUCCEEDED(pInterface->GetValue(tmp, size)))
    {
        std::wstring str = tmp;
        // do some work which doesn't throw
    }
    delete[] tmp;
}

Is it safe and portable to do this instead?

if (SUCCEEDED(pInterface->GetSize(&size))
{
    std::wstring str;
    str.resize(size-1);
    if (SUCCEEDED(pInterface->GetValue(&str[0], size)))
    {
        // do some work
    }
}

Now, obviously this works (doesn't crash/corrupt memory) or I wouldn't have asked, but I'm mostly wanting to know if there's a compelling reason not to do this.

Edit: Actually I had change this to .resize(size-1), as apparently the null character is taken into account for you (by VS 2010 anyway). Using .resize(size) ended up where appending to the end of the string was resulting in:

str.resize(size);
pInterface->GetValue(&str[0], size);
str contains L"foo\0";
str += L"bar";
str contains L"foo\0bar";

Trying to use the resulting str.c_str ends up looking like L"foo" due to the null in the middle.

+5  A: 

As AraK points out, the string storage might not be contiguous, though this is unlikely. You could also consider using a vector:

if (SUCCEEDED(pInterface->GetSize(&size))
{
    std::vector <wchar_t> vtmp( size );
    if (SUCCEEDED(pInterface->GetValue( & vtmp[0], size)))
    {
        std::wstring str = & vtmp[0];
        // or maybe don't bother with the string - just use the vector
    }
}

which is more likely to be exception safe.

anon
Why is this more likely to be exception safe? Is there a scenario under which my code above is not exception safe?
LCC
@LCC Yes, if GetValue or operator-> on the interface can throw, you have a leak. General rule - whenever you see a new or delete in your code, try to remove it.
anon
Also, according to cursory research, vector isn't guaranteed to be contiguous either! It suffers the same problem as using std::wstring, except now you have this extra layer of unneeded complexity.http://groups.google.com/group/comp.lang.c++/msg/408d058c256d7699?pli=1
LCC
@LCC: `vector` will always be contiguous. IIRC it wasn't explicitly stated in C++98, but was implied by the requirements. It is explicitly stated in C++03.
James McNellis
Obviously the first snippet leaks (as delete[] is never called). The second snippet won't leak, the destructor for "str" will be called, cleaning up the memory.
LCC
@LCC Vector _is_ guaranteed to be contiguous - this was fixed in a TC years ago.
anon
Ahh yeah, I see the line in the newer standard, 23.2.4.1. Thanks.
LCC
@LCC and that comp.lang.c++ post you reference is 7 years old. If you are going to use Usenet as a source, I suggest not looking at anything more than a year or so old, and not looking at comp.lang.c++ at all - use comp.lang.c++.moderated, which is of a much higher quality.
anon
I used Google. As I said, cursory search.
LCC