5
votes

When the function requires a char*, can you pass in a shared_ptr?

I'm reading in a whole text file (length = 100), and want to store the char's into a char[] array. The naive way I used was this:

ifstream dictFile(fileName);
size_t fileLength = 100;
char* readInBuffer(new char[fileLength]);
dictFile.read(readInBuffer, fileLength);
//processing readInBuffuer..............
delete[] readInBuffer;
dictFile.close();

Of course there is memory leak if an exception is thrown before the delete[] statement. I'm wondering if I can use shared_ptr readInBuffer(new char[fileLength]); But the function prototype

read ( char* s, streamsize n )

won't accept a smart pointer as input? Any tricks?

Edit: I'm trying to write something like this:

shared_ptr<char[]> readInBuffer(new char[fileLength]);
dictFile.read(readInBuffer.get(), fileLength);

But it won't compile.

3
You already have part of the answer in your question - a regular pointer doesn't have a get() method, but a smart pointer does and it does exactly what you're asking for.Mark Ransom
A shared_ptr isn't smart enough to manage an array. A unique_ptr, however, is, if you give it a custom deleter.Pete Becker

3 Answers

6
votes

Rather than using a pointer, you can use a vector instead.

std::vector<char> readInBuffer(fileLength);
dictFile.read(&readInBuffer[0], fileLength);
4
votes

BIG FAT WARNING: creating a shared_ptr that points to an array provokes undefined behaviour, because the smart pointer will delete the pointer, not delete[] it. Use a vector instead!

Leaving this here because it might serve as a useful warning. Original answer follows...

The get() function returns the underlying raw pointer. You already wrote this in your code!

shared_ptr<char> readInBuffer(new char[fileLength]);
dictFile.read(readInBuffer.get(), fileLength);

The same result can be achieved with &*readInBuffer.

Of course, you have to be certain that dictFile.read() doesn't delete the pointer, or demons might fly out of your nose.

1
votes

No, you can't pass a shared_ptr. But you can create one, and call its get() member function to get a copy of the raw pointer to pass to the function. However, a shared_ptr doesn't deal with arrays; that's what vector is for. But you can use a unique_ptr to an array to manage that object:

std::unique_ptr<char[], std::default_delete<char[]> ptr(new char[whatever]);
f(ptr.get());

There may be a shorter way to write that first line, but I don't have time to dig it out.