5

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.

digit plumber
  • 1,140
  • 2
  • 14
  • 27
  • possible duplicate of [getting a normal ptr from shared\_ptr?](http://stackoverflow.com/questions/505143/getting-a-normal-ptr-from-shared-ptr) – D.Shawley Nov 15 '12 at 19:58
  • 1
    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 Nov 15 '12 at 20:01
  • 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 Nov 15 '12 at 20:15

3 Answers3

6

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

std::vector<char> readInBuffer(fileLength);
dictFile.read(&readInBuffer[0], fileLength);
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
5

BIG FAT WARNING: creating a std::shared_ptr<char> that points to an array provokes undefined behaviour, because the smart pointer will delete the pointer, not delete[] it. Use a std::shared_ptr<char[]> 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.

SRG
  • 498
  • 7
  • 19
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • Without a custom deleter, `unique_ptr` will simply call `delete p` on the stored pointer. Since the memory was allocated with array new, this produces undefined behavior. – Pete Becker Nov 15 '12 at 20:07
  • Ouch, yes, you're right. I'll leave this here and add a big fat warning. – Thomas Nov 15 '12 at 20:10
  • Ouch, back. `` My comment ended up talking about `unique_ptr` when I meant `shared_ptr`. `shared_ptr` simply doesn't deal with arrays; there are no custom deleters for `shared_ptr`. `unique_ptr` can be used here, though. – Pete Becker Nov 15 '12 at 20:13
1

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165