auto for type declaration

28
auto for Type Declaration Auto variables have the type of their initializing expression: auto x1 = 10; //either syntax is auto y1(20); //fine map<int, string> m; auto i1 = m.begin(); Const/volatile and reference/pointer adornments may be added: const auto *x2 = &x1; const auto& i2 = m; //i2 is map&

Upload: xuan

Post on 18-Jan-2016

158 views

Category:

Documents


2 download

DESCRIPTION

auto for Type Declaration. Auto variables have the type of their initializing expression: auto x1 = 10; //either syntax is auto y1(20); //fine map< int , string> m; auto i1 = m.begin (); Const/volatile and reference/pointer adornments may be added: - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: auto for Type Declaration

auto for Type Declaration

Auto variables have the type of their initializing expression:auto x1 = 10; //either syntax is

auto y1(20); //fine

map<int, string> m;

auto i1 = m.begin();

Const/volatile and reference/pointer adornments may be added:const auto *x2 = &x1;const auto& i2 = m; //i2 is map&

Page 2: auto for Type Declaration

auto for Type Declaration

Type deduction for auto is akin to that for template parameters.

Auto can be used to declare multiple variables:void f(string& s){ auto temp = s, *ptr =&s;}

Each initiation must yield the same deduced type (like template deduction):

auto i = 5, d = 10.33; //error

Page 3: auto for Type Declaration

nullptr

A new keyword, indicates a null pointer. Convertible to any pointer type and to bool, but

nothing else. Can’t be used as an integral value Traditional use of 0 and NULL remain valid.const char * p = nullptr;if (p)int I = nullptr; //errorif (nullptr == 0) //errorint *p1 = nullptr;int *p2 = 0;int *p3 = NULL;if (p1 == p2 == p3) …

Page 4: auto for Type Declaration

nullptr

Only nullptr is unambiguously a pointer:

void f(int *ptr);void f(int val);

…f(nullptr); //f(int*)f(0); //f(int)f(NULL); //probably f(int)

Page 5: auto for Type Declaration

How Smart Are your pointers?

C++98 auto_ptr

TR1 shared_ptr and weak_ptr

C++0x Support for allocators and unique_ptr

Page 6: auto for Type Declaration

auto_ptr

auto_ptr is a smart pointer template that provides auto destruction of dynamically allocated memory when the pointer goes out of scope.

#include <memory> // auto_ptr’s header

class MyValue { . . . }; // Same as before void process(int val) { . . . } // Same as before

Page 7: auto for Type Declaration

auto_ptrint main() { std::auto_ptr<MyValue> p(new MyValue(5)); while(--(*p) >= 0)

{std::cout << "Enter a value: ";int value; std::cin >> value;process(value);

} // An explicit call to delete is no longer necessary

. . . }

output: CTOREnter a value: 6Enter a value: 23Enter a value: 17DTOR

Page 8: auto for Type Declaration

auto_ptr

auto_ptr objects contain an ownership indicator. This is used for management of dynamic memory in the event multiple auto_ptr objects refer to the same element_type object. This is different behavior than conventional deep-copy and reference counting schemes for smart pointers.

Page 9: auto for Type Declaration

auto_ptr usageclass Foo{ public : Foo(int v); ~Foo(); void display(void); private : int m_val; };

Foo::Foo(int v) : m_val(v) { cout << "ctor - " << m_val << endl; }

Foo::~Foo() { cout << "dtor - " << m_val << endl; }

void Foo::display(void){ cout << ”Value = ” << m_val” << endl;}

Page 10: auto for Type Declaration

auto_ptr usageint main() { std::auto_ptr<Foo> p1(new Foo(1)); std::auto_ptr<Foo> p2(new Foo(2)); p1->display(); . . . }

output:ctor - 1ctor – 2Value = 1dtor – 2dtor - 1

Page 11: auto for Type Declaration

auto_ptr

Relinquishing ownership without releasing memory...

int main() { std::auto_ptr<Foo> p1(new Foo(1)); std::auto_ptr<Foo> p2(new Foo(2)); p1.release(); // Memory leak . . . }output: ctor - 1

ctor – 2dtor - 2

Page 12: auto for Type Declaration

auto_ptr

The right way to use release()... int main() { std::auto_ptr<Foo> p1(new Foo(1)); std::auto_ptr<Foo> p2(new Foo(2)); delete p1.release(); . . . }output: ctor - 1

ctor - 2dtor - 1dtor - 2

Page 13: auto for Type Declaration

Ownership

Transfer of ownership… int main() { std::auto_ptr<Foo> p1(new Foo(1));

// p1 owns the object std::auto_ptr<Foo> p2; p2 = p1; // now p2 owns the object std::auto_ptr<Foo> p3(p2);

// now p3 owns it . . . }output: ctor - 1

dtor - 1

Page 14: auto for Type Declaration

Ownershipvoid bar(std::auto_ptr<Foo> ptr){ std::cout << "Some processing" << std::endl;} int main() {

std::auto_ptr<Foo> p1(new Foo(1));std::cout << "Before bar()" << std::endl;bar(p1);std::cout << "After bar()" << std::endl;// What does p1 point to here?

. . .}

output: ctor – 1Before bar()Some processingdtor – 1After bar()

Page 15: auto for Type Declaration

Ownership

Change bar()’s signature to this… void bar(std::auto_ptr<Foo> &ptr) { . . . }

and the problem goes away…

output: ctor – 1Before bar()Some processingAfter bar()dtor – 1

Page 16: auto for Type Declaration

Smart Pointers

Smart pointers simplify resource management. Prevention of leaks. Don’t have to call “delete”

auto_ptr is constraining Designed for exclusive ownership. Has strange copy semantics.

Can’t have a container of auto_ptrs. A standard shared-ownership smart pointers needed:

Should offer “normal” copy semantics. Hence may be stored in containers.

Many versions have been created/deployed. Typically based on reference counting.

Page 17: auto for Type Declaration

shared_ptr Declared in <memory> A reference-counting smart pointer. Pointed-to-resources are released when the ref.count

(RC)->0.

{ shared_ptr<Widget> p1(new Widget);

shared_ptr<Widget> p2(p1);

p1->doThis(); if (p2) p2->doThat();

p2 = nullptr;… //delete is called automatically}

Page 18: auto for Type Declaration

shared_ptr constructors Default, copy, from raw pointershared_ptr<Widget> pw1;shared_ptr<Widget> pw2(pw1);shared_ptr<Widget> pw3(new Widget); //typicalshared_ptr<Widget> pw4 = new Widget; //error

From compatible unique_ptr, auto_ptr, shared_ptr or weak_ptr.unique_ptr<Widget> makeUP();auto_ptr<Widget> makeAP();shared_ptr<Widget> pw5(makeUP());shared_ptr<Widget> pw6(makeAP());shared_ptr<const Widget> pw7(pw3);

Page 19: auto for Type Declaration

shared_ptr Constructors From this:

It’s a raw pointer, but other shared_ptrs might already exist!

shared_ptr<ISomething> Widget::getISomething(){ return shared_ptr<ISomething>(this);}

//dangerous, could create a new ref cnt!

shared_ptr<ISomething> Widget::getISomething(){ return shared_from_this();} //Okay

Inheritance from enable_shared_from _this is required:

class Widget: public ISomething, public std::enable_shared_from_this<Widget> { … };

Page 20: auto for Type Declaration

Some shared_ptr features

Access to underlying new pointer: Usefule for communicating with legacy APIs.

void oldAPI(Widget *pWidget);shared_ptr<Widget> spw(newWidget);oldAPI(spw.get());

Access to reference count:

if (spw.unique()) ….size_t refs = spw.use_count();

Page 21: auto for Type Declaration

shared_ptr and incomplete types

Unlike auto_ptr (but like unique_ptr), shared_ptr supports incomplete types:class Widget; //incomplete typeauto_ptr<Widget> ap; //undefined behaviorshared_ptr<Widget> sp; //fineunique_ptr<Widget> up; //also fine

shared_ptr thus allows common coupling-reduction strategies. E.g. pimpl (private implementation)

Page 22: auto for Type Declaration

Pimpl

The Pimpl idiom describes a way for making your header files impervious to change. You often hear advices like "Avoid change your public interface!" So you can modify your private interface, but how can you avoid recompilation when your header file defines the private methods. This is what the Pimpl does – Reduce compilation damages when your private interface changes.

Page 23: auto for Type Declaration

Pimpl// In MyClass.h

class MyClassImp; // forward declaration of Pimpl

class MyClass { public:

MyClass (); ~MyClass(); MyClass( const MyClass &rhs ); MyClass& operator=( MyClass ); void Public_Method();

private: MyClassImp *pimpl_; // the Pimpl

};

The header defines a forward declaration of the Pimpl and other public interface. It stores a private Pimpl_ member pointer and that is all the client will ever see. There will never be any change unless you change the public interface, which you already know you shouldn't.

Page 24: auto for Type Declaration

shared_ptr and inheritance conversions

auto_ptr fails to support some inheritance-based conversions that shared_ptr offers:

class Base {..};class Derived:public Base {..};auto_ptr<Derived> create();void use(auto_ptr<Base>);use(create()); //error

shared_ptr<Derived> create();void use(shared_ptr<Base>);use(create()); //fine

Page 25: auto for Type Declaration

weak_ptr Weak_ptrs are like raw pointers, but they know

when they dangle: When a resource’s reference count-> 0, its weak_ptrs

expire. Shared_ptr releasing a resouce expires all weak_ptrs

shared_ptr<Widget> spw(new Widget); //RC = 1weak_ptr<Widget> wpw(spw); //RC = 1if (!wpw.expired()) … //if RC >= 1

Useful for “observing” data structures managed by others. Safer than raw pointers. Raw pointers might dangle.

Page 26: auto for Type Declaration

weak_ptr

Also to facilitate cyclic structures that would otherwise foil RC:

ObjectA

ObjectB

RC unfriendly

shared_ptrshared_ptr

ObjectA

ObjectB

Raw pointershared_ptr

ObjectA

ObjectB

weak_ptrshared_ptr

RC friendly, safer

RC friendly, not safe

Page 27: auto for Type Declaration

weak_ptr Weak_ptrs aren’t really smart pointers.

No deferencing operators (no -> or *) No implicit nullness test

To use weak_ptr as a pointer, create a shared_ptr from it.

weak_ptr<Widget> wpw(spw);wpw->doSomething; //won’t compile

//create a shared_ptr; throws if wpw’s expired.shared_ptr<Widget> pw1(wpw);

//pw2 is null if wpw’s expired.shared_ptr<Widget> pw2(wpw.lock());

if (pw2)pw2->doSomething();

Page 28: auto for Type Declaration

Cost of shared_ptrs

Sample implementation 2 words in size (pointer to object, pointer to RC)

Uses dynamically allocated memory for the RC. Resource release (i.e. deletion) via a virtual function call Incurs cost for weak_ptr count even if no weak_ptrs are

used.

Shared_ptr<T>T Object

RefCountWeak count

Deleter

AllocatorOptional