问题
I like the new pointer types in C++11, but sometimes I still need a raw pointer. Something that makes me increasingly sad about "raw" types in C++, however, is their habit of initializing as undefined when not given an explicit value. As I use std::shared_ptr<> and the like more often, this need to initialize raw pointers to null feels increasingly brittle and unnecessary. I'm talking about:
class foo
{
...
std::shared_ptr< bar > pb; // Initially null in whatever constructor.
std::unique_ptr< dar > pd; // Likewise.
std::weak_ptr< gar > pg; // And again.
lar* pr; // Uh-oh! Who knows what this is? Better remember to initialize...
};
foo::foo( int j )
: pr( nullptr )
{...}
foo::foo( const string& s )
: pr( nullptr )
{...}
... etc.: many tedious and error-prone constructor definitions follow.
What I'd like, therefore, is a "raw pointer with null initialization." Something like:
class foo
{
...
std::shared_ptr< bar > pb; // Initially null in whatever constructor.
std::unique_ptr< dar > pd; // Likewise.
std::weak_ptr< gar > pg; // And again.
raw_ptr< lar > pr; // Once more with feeling.
};
foo::foo( int j )
{...} // No explicit pointer initialization necessary.
foo::foo( const string& s )
{...}
...
More precisely, what I want is a simple, cheap type that acts exactly like a raw pointer in every way except that its default constructor initializes it to nullptr.
My question: (1) Does such a thing already exist in the standard library? (2) If not, what would be the most elegant/smallest way to accomplish an implementation of this type?
P.S. I'm not interested in Boost or any other libraries, unless perhaps it is a header-only library in a single file. Smallness and simplicity are of the essence.
回答1:
C++11 allows in class initialization of data members.
class foo
{
// ...
lar *pr = nullptr;
};
That'll always initialize pr
to nullptr
unless you assign another value in the constructor.
回答2:
It looks like you need "World’s Dumbest Smart Pointer" which has been proposed as an addition to a future C++ standard template library. You can see the proposal here: "A Proposal for the World’s Dumbest Smart Pointer" and here: "A Proposal for the World’s Dumbest Smart Pointer, v2" and here: "A Proposal for the World’s Dumbest Smart Pointer, v3"
The proposal contains a potential partial implementation which you may be able to adapt for use with the compiler you are currently using. The implementation is similar to the almost_raw_ptr solution provided by Mark Ransom. A web search for exempt_ptr will give more details.
A proposal for the World’s Dumbest Smart Pointer, v3 has "Renamed exempt_ptr to observer_ptr" see the linked doument for other changes.
回答3:
template<typename T>
class almost_raw_ptr
{
public:
almost_raw_ptr(T* p = nullptr) : m_p(p) {}
T* operator=(T* p) { m_p = p; return p; }
operator T*() const { return m_p; }
T* operator->() const { return m_p; }
T& operator*() const { return *m_p; }
T& operator[](int i) const { return m_p[i]; }
private:
T* m_p;
};
This won't work if you need a pointer or a reference to the actual raw pointer, but it should work for everything else.
回答4:
When you use a raw pointer and expect the value 0
to express that the pointer is not yet initialized, the value 0
is in a sense a "sentinel value", or a "magic cookie." Think of a magic cookie as a special value that indicates state, but is otherwise indistinguishable from normal, valid values for that datatype.
Magic cookies being Bad for all the usual reasons might be triggering your sense that this is brittle and ultimately not needed. A solution that doesn't use a sentinel value might feel better.
One such solution is to use boost::optional
:
typedef Foo* FooPtr;
boost::optional <FooPtr> foo;
// ...
if (!foo)
{
// the pointer is not yet initialized
}
else
{
// the pointer IS initialized
Foo* theFoo = *foo;
}
Initializing the pointer is simple:
foo = new Foo;
optional
is not a sentinel value because you do not store a special value of Foo*
to indicate that the pointer isn't initialized. The only job that optional
does is to say "yes" or "no" in answer to the question "is the pointer initialized?"
来源:https://stackoverflow.com/questions/17534210/trivial-raw-pointer-that-self-initializes-to-nullptr-in-c