SlideShare a Scribd company logo
Mateusz Pusz
November 15, 2017
POINTLESS POINTERS
HOW TO MAKE OUR INTERFACES EFFICIENT?
code::dive 2017 | Pointless Pointers
WHAT IS A POINTER?
2
A pointer is a programming language data type whose value refers
directly to (or "points to") another value stored elsewhere in the
computer memory using its address.
-- Wikipedia
code::dive 2017 | Pointless Pointers
WHAT IS A POINTER?
2
code::dive 2017 | Pointless Pointers
WHAT IS A POINTER?
3
Pointers due to their ambiguous nature are the source of most
problems and bugs in C++ code. Lack of understanding between
code architect and the user results in crashes, asserts and memory
leaks!!!
-- Mateusz Pusz ☺
code::dive 2017 | Pointless Pointers
WHAT IS A POINTER?
3
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
Bu er Overflows
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
Bu er Overflows
Hangs!
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
Bu er Overflows
Hangs!
Crashes!
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
Bu er Overflows
Hangs!
Crashes!Stability!!!
4
code::dive 2017 | Pointless Pointers
POINTERS MISUSE LEADS TO
Null Pointer Dereference
Resource leaks
Bu er Overflows
Hangs!
Crashes!Stability!!!
Security!!!
4
B* a(A* ptr) { /* ... */; return b(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
B* c(A* ptr) { /* ... */; return d(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
B* c(A* ptr) { /* ... */; return d(ptr); }
B* d(A* ptr) { /* ... */; return e(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
B* c(A* ptr) { /* ... */; return d(ptr); }
B* d(A* ptr) { /* ... */; return e(ptr); }
B* e(A* ptr) { /* ... */; return f(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
B* c(A* ptr) { /* ... */; return d(ptr); }
B* d(A* ptr) { /* ... */; return e(ptr); }
B* e(A* ptr) { /* ... */; return f(ptr); }
B* f(A* ptr) { /* ... */; return g(ptr); }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; return b(ptr); }
B* b(A* ptr) { /* ... */; return c(ptr); }
B* c(A* ptr) { /* ... */; return d(ptr); }
B* d(A* ptr) { /* ... */; return e(ptr); }
B* e(A* ptr) { /* ... */; return f(ptr); }
B* f(A* ptr) { /* ... */; return g(ptr); }
B* g(A* ptr) { /* ... */; return *ptr; }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
5
B* a(A* ptr) { /* ... */; assert(ptr); return b(ptr); }
B* b(A* ptr) { /* ... */; assert(ptr); return c(ptr); }
B* c(A* ptr) { /* ... */; assert(ptr); return d(ptr); }
B* d(A* ptr) { /* ... */; assert(ptr); return e(ptr); }
B* e(A* ptr) { /* ... */; assert(ptr); return f(ptr); }
B* f(A* ptr) { /* ... */; assert(ptr); return g(ptr); }
B* g(A* ptr) { /* ... */; assert(ptr); return *ptr; }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
6
B* a(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return b(ptr); }
B* b(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return c(ptr); }
B* c(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return d(ptr); }
B* d(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return e(ptr); }
B* e(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return f(ptr); }
B* f(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return g(ptr); }
B* g(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return *ptr; }
code::dive 2017 | Pointless Pointers
PROBLEM DEFINITION
7
B* func(A* arg);
code::dive 2017 | Pointless Pointers
QUIZ - GUESS WHAT?
8
person* add(name* n);
code::dive 2017 | Pointless Pointers
QUIZ - GUESS WHAT?
9
person* add(name* n);
code::dive 2017 | Pointless Pointers
QUIZ - GUESS WHAT?
Is it better now?
Is it enough?
Do you know how to use that function?
Do you know how to implement that function?
9
person* add(name* n);
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #1
10
person* add(name* n);
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #1
Is that a valid usage of add() interface?
What are potential problems with above code?
10
person* add(name* n);
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #2
11
person* add(name* n);
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #2
Is that a valid usage of add() interface?
11
person* add(name* n);
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #3
12
person* add(name* n);
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #3
Is that a valid usage of add() interface?
What are potential problems with above code?
12
person* add(name* n);
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #4
13
person* add(name* n);
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
ADD() USAGE – TAKE #4
Is that a valid usage of add() interface?
What are potential problems with above code?
13
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
1
2
3
4
WHICH ONE IS CORRECT?
14
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
1
2
3
4
QUIZ - MATCH IMPLEMENTATION
std::deque<person> people;
person* add(name* n)
{
people.emplace_back((n != nullptr) ? *n : "anonymous");
return &people.back();
}
15
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
QUIZ - MATCH IMPLEMENTATION
1
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
2
3
4
person* add(name* n)
{
assert(n);
int num = 0;
for(auto ptr = n; *ptr != ""; ++ptr)
++num;
person* p = new person[num];
for(auto i = 0; i<num; ++i)
p[i].name(n[i]);
return p;
}
16
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
code::dive 2017 | Pointless Pointers
QUIZ - MATCH IMPLEMENTATION
1
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
2
3
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
4
person* add(name* n)
{
assert(n != nullptr);
return new person{n};
}
17
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
code::dive 2017 | Pointless Pointers
QUIZ - MATCH IMPLEMENTATION
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
1
2
3
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
4
std::deque<person> people;
person* add(name* n)
{
if(n == nullptr)
return nullptr;
auto it = find_if(begin(people), end(people),
[&](person& p)
{ return p.name() == *n; });
if(it != end(people))
return nullptr;
people.emplace_back(*n);
return &people.back();
}
18
code::dive 2017 | Pointless Pointers
QUIZ - MATCH IMPLEMENTATION
void foo()
{
person* p = add(new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
1
2
3
4
19
person*
add(name* n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
20
person*
add(name* n);
std::unique_ptr<person>
add(std::unique_ptr<name> n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
20
person*
add(name* n);
std::unique_ptr<person>
add(std::unique_ptr<name> n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
Do you know how to use that function?
Do you know how to implement that function?
20
person*
add(name* n)
{
assert(n != nullptr);
return new person{n};
}
void foo()
{
person* p = add(
new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #1
21
void foo()
{
auto p = add(
std::make_unique<name>("Mateusz Pusz"));
assert(p != nullptr);
process(p->id(), p->name());
}
std::unique_ptr<person>
add(std::unique_ptr<name> n)
{
assert(n != nullptr);
return std::make_unique<person>(std::move(n));
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #1
person*
add(name* n)
{
assert(n != nullptr);
return new person{n};
}
void foo()
{
person* p = add(
new name{"Mateusz Pusz"});
assert(p != nullptr);
process(p->id(), p->name());
delete p;
}
21
person*
add(name* n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
22
person*
add(name* n);
person&
add(std::optional<name> n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
22
person*
add(name* n);
person&
add(std::optional<name> n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
Do you know how to use that function?
Do you know how to implement that function?
22
std::deque<person> people;
person* add(name* n)
{
people.emplace_back(
(n != nullptr) ? *n : "anonymous");
return &people.back();
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #2
23
std::deque<person> people;
person& add(std::optional<name> n)
{
people.emplace_back(
n ? std::move(*n) : "anonymous");
return people.back();
}
void foo()
{
person& p = add(name{"Mateusz Pusz"});
process(p.id(), p.name());
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #2
std::deque<person> people;
person* add(name* n)
{
people.emplace_back(
(n != nullptr) ? *n : "anonymous");
return &people.back();
}
void foo()
{
name n{"Mateusz Pusz"};
person* p = add(&n);
if(p != nullptr)
process(p->id(), p->name());
}
23
person*
add(name* n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
24
person*
add(name* n);
std::tuple<person&, bool>
add(name n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
24
person*
add(name* n);
std::tuple<person&, bool>
add(name n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
Do you know how to use that function?
Do you know how to implement that function?
24
std::deque<person> people;
person* add(name* n)
{
if(n == nullptr) return nullptr;
auto it = find_if(
begin(people), end(people),
[&](person& p) { return p.name() == *n; });
if(it != end(people))
return nullptr;
people.emplace_back(*n);
return &people.back();
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #3
25
std::deque<person> people;
std::tuple<person&, bool> add(name n)
{
auto it = find_if(
begin(people), end(people),
[&](person& p) { return p.name() == n; });
if(it != end(people))
return { *it, false };
people.emplace_back(std::move(n));
return { people.back(), true };
}
void foo()
{
auto r = add(name{"Mateusz Pusz"});
if(std::get<bool>(r))
process(std::get<0>(r).id(), std::get<0>(r).name());
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #3
std::deque<person> people;
person* add(name* n)
{
if(n == nullptr) return nullptr;
auto it = find_if(
begin(people), end(people),
[&](person& p) { return p.name() == *n; });
if(it != end(people))
return nullptr;
people.emplace_back(*n);
return &people.back();
}
void foo()
{
name* n = new name{"Mateusz Pusz"};
person* p = add(n);
if(p != nullptr)
process(p->id(), p->name());
delete n;
}
25
person*
add(name* n);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
26
person*
add(name* n);
std::vector<person>
add(std::vector<name> names);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
26
person*
add(name* n);
std::vector<person>
add(std::vector<name> names);
code::dive 2017 | Pointless Pointers
IS THERE A BETTER SOLUTION?
Do you know how to use that function?
Do you know how to implement that function?
26
person* add(name* n)
{
assert(n);
int num = 0;
for(auto ptr = n; *ptr != ""; ++ptr)
++num;
person* p = new person[num];
for(auto i = 0; i<num; ++i)
p[i].name(n[i]);
return p;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #4
27
std::vector<person> add(std::vector<name> names)
{
std::vector<person> p;
p.reserve(names.size());
for(auto& n : names)
p.emplace_back(std::move(n));
return p;
}
void foo()
{
auto people = add({"Mateusz Pusz", "Jan Kowalski"});
for(auto& p : people)
process(p.id(), p.name());
}
code::dive 2017 | Pointless Pointers
USING C++ THE RIGHT WAY – CASE #4
person* add(name* n)
{
assert(n);
int num = 0;
for(auto ptr = n; *ptr != ""; ++ptr)
++num;
person* p = new person[num];
for(auto i = 0; i<num; ++i)
p[i].name(n[i]);
return p;
}
void foo()
{
name names[] = {"Mateusz Pusz", "Jan Kowalski", ""};
person* people = add(names);
assert(people != nullptr);
for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i)
process(people[i].id(), people[i].name());
delete[] people;
}
27
Pointless Pointers - How to make our interfaces efficient?
ARGUMENT TYPE POINTER ARGUMENT DECLARATION
Mandatory big value void foo(A* in);
Output function argument void foo(A* out);
Array void foo(A* array);
Optional value void foo(A* opt);
Ownership passing void foo(A* ptr);
code::dive 2017 | Pointless Pointers
POINTERS USAGE IN ANSI C
29
ARGUMENT TYPE POINTER ARGUMENT DECLARATION
Mandatory big value void foo(A* in);
Output function argument void foo(A* out);
Array void foo(A* array);
Optional value void foo(A* opt);
Ownership passing void foo(A* ptr);
code::dive 2017 | Pointless Pointers
POINTERS USAGE IN ANSI C
Pointer ambiguity makes it really hard to understand the intent of the
interface author.
29
ARGUMENT TYPE POINTER ARGUMENT DECLARATION
Mandatory big value void foo(const A& in);
Output function argument A foo(); or std::tuple<...> foo(); or void foo(A& out);
Array void foo(const std::vector<A>& a);
Optional value void foo(std::optional<A> opt); or void foo(A* opt);
Ownership passing void foo(std::unique_ptr<A> ptr);
code::dive 2017 | Pointless Pointers
DOING IT C++ WAY
30
ARGUMENT TYPE POINTER ARGUMENT DECLARATION
Mandatory big value void foo(const A& in);
Output function argument A foo(); or std::tuple<...> foo(); or void foo(A& out);
Array void foo(const std::vector<A>& a);
Optional value void foo(std::optional<A> opt); or void foo(A* opt);
Ownership passing void foo(std::unique_ptr<A> ptr);
code::dive 2017 | Pointless Pointers
DOING IT C++ WAY
Use above Modern C++ constructs to explicitly state your design intent.
30
B foo(std::optional<A> arg);
const A& foo(const std::array<A, 3>& arg);
std::unique_ptr<B> foo(A arg);
std::vector<B> foo(const A& arg);
code::dive 2017 | Pointless Pointers
QUIZ – GUESS WHAT?
31
int count_lower(const char* ptr, size_t size);
void add_2(int* ptr, size_t size);
code::dive 2017 | Pointless Pointers
C++17 AND C++20: WHAT ABOUT POINTER AND A SIZE
ANSI C -> C++14
ANSI C -> C++14
32
int count_lower(const char* ptr, size_t size);
void add_2(int* ptr, size_t size);
int count_lower(std::string_view txt);
void add_2(std::span<int> array);
code::dive 2017 | Pointless Pointers
C++17 AND C++20: WHAT ABOUT POINTER AND A SIZE
ANSI C -> C++14
ANSI C -> C++14
C++17
C++20
32
TAKEAWAYS
C++ is a powerful tool:
• strong type system
• better abstractions
• templates
• C++ STD library
code::dive 2017 | Pointless Pointers
C++ IS NOT ANSI C!!!
34
Pointless Pointers - How to make our interfaces efficient?
Pointless Pointers - How to make our interfaces efficient?

More Related Content

PDF
C++ Programs
ODP
Hom Class
ODP
Hom Class
PDF
Automatically Describing Program Structure and Behavior (PhD Defense)
PPTX
Go之道
PDF
.NET 2015: Будущее рядом
PDF
KISS - im Prinzip ganz einfach
PDF
Deductive verification of unmodified Linux kernel library functions
C++ Programs
Hom Class
Hom Class
Automatically Describing Program Structure and Behavior (PhD Defense)
Go之道
.NET 2015: Будущее рядом
KISS - im Prinzip ganz einfach
Deductive verification of unmodified Linux kernel library functions

What's hot (19)

PDF
The Error of Our Ways
DOCX
Dns server clients (actual program)
DOC
Network lab manual
PDF
Effective Object Oriented Design in Cpp
PPT
DOCX
Network lap pgms 7th semester
PDF
Defcon 23 - Daniel Selifonov - drinking from LETHE
PDF
Что нам готовит грядущий C#7?
PPT
Algorithm
PDF
Enrichment lecture EE Technion (parts A&B) also including the subject of VHDL...
PPTX
Write Your Own Compiler in 24 Hours
PDF
How to Parse a File (DDD North 2017)
DOCX
Computer science project work
DOCX
rubik_solve
PPTX
Mixing C++ & Python II: Pybind11
PDF
Good Code
DOCX
Computer Networks Lab File
PDF
CBSE Question Paper Computer Science with C++ 2011
TXT
c++ program for Railway reservation
The Error of Our Ways
Dns server clients (actual program)
Network lab manual
Effective Object Oriented Design in Cpp
Network lap pgms 7th semester
Defcon 23 - Daniel Selifonov - drinking from LETHE
Что нам готовит грядущий C#7?
Algorithm
Enrichment lecture EE Technion (parts A&B) also including the subject of VHDL...
Write Your Own Compiler in 24 Hours
How to Parse a File (DDD North 2017)
Computer science project work
rubik_solve
Mixing C++ & Python II: Pybind11
Good Code
Computer Networks Lab File
CBSE Question Paper Computer Science with C++ 2011
c++ program for Railway reservation
Ad

Similar to Pointless Pointers - How to make our interfaces efficient? (20)

PDF
C++ aptitude
PPTX
What's New in C++ 11/14?
PDF
Checking the Cross-Platform Framework Cocos2d-x
PPTX
Introduction to pointers in c plus plus .
PPTX
Pointers in C++ object oriented programming
PPTX
PPTX
Data structure and Algorithms (C++).pptx
PPT
Beware of Pointers
PDF
CS225_Prelecture_Notes 2nd
PDF
C++ L06-Pointers
PDF
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
PPT
Link list
PPT
Cppt 101102014428-phpapp01
PPT
Advance features of C++
PPTX
stack.pptx
PDF
Zero, one, two, Freddy's coming for you
PPT
C++ Memory Management
PPTX
How vectors work in C++ and their allocation of memory
PPTX
Object oriented programming slides for presentation
PPTX
C++ 11 Features
C++ aptitude
What's New in C++ 11/14?
Checking the Cross-Platform Framework Cocos2d-x
Introduction to pointers in c plus plus .
Pointers in C++ object oriented programming
Data structure and Algorithms (C++).pptx
Beware of Pointers
CS225_Prelecture_Notes 2nd
C++ L06-Pointers
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Link list
Cppt 101102014428-phpapp01
Advance features of C++
stack.pptx
Zero, one, two, Freddy's coming for you
C++ Memory Management
How vectors work in C++ and their allocation of memory
Object oriented programming slides for presentation
C++ 11 Features
Ad

More from Mateusz Pusz (15)

PDF
Free Lunch is Over: Why is C++ so Important in the Modern World?
PDF
A Physical Units Library for the Next C++
PDF
Striving for ultimate Low Latency
PDF
Rethinking the Way We do Templates in C++
PDF
C++11 Was Only the Beginning
PDF
Implementing a Physical Units Library for C++
PDF
Effective replacement of dynamic polymorphism with std::variant
PDF
Implementing Physical Units Library for C++
PDF
C++ Concepts and Ranges - How to use them?
PDF
Effective replacement of dynamic polymorphism with std::variant
PDF
Git, CMake, Conan - How to ship and reuse our C++ projects?
PDF
Beyond C++17
PDF
Striving for ultimate Low Latency
PDF
Small Lie in Big O
PDF
std::shared_ptr<T> - (not so) Smart hammer for every pointy nail
Free Lunch is Over: Why is C++ so Important in the Modern World?
A Physical Units Library for the Next C++
Striving for ultimate Low Latency
Rethinking the Way We do Templates in C++
C++11 Was Only the Beginning
Implementing a Physical Units Library for C++
Effective replacement of dynamic polymorphism with std::variant
Implementing Physical Units Library for C++
C++ Concepts and Ranges - How to use them?
Effective replacement of dynamic polymorphism with std::variant
Git, CMake, Conan - How to ship and reuse our C++ projects?
Beyond C++17
Striving for ultimate Low Latency
Small Lie in Big O
std::shared_ptr<T> - (not so) Smart hammer for every pointy nail

Recently uploaded (20)

PDF
Approach and Philosophy of On baking technology
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
cuic standard and advanced reporting.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Machine Learning_overview_presentation.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Encapsulation theory and applications.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
Approach and Philosophy of On baking technology
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Building Integrated photovoltaic BIPV_UPV.pdf
Big Data Technologies - Introduction.pptx
cuic standard and advanced reporting.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Mobile App Security Testing_ A Comprehensive Guide.pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Advanced methodologies resolving dimensionality complications for autism neur...
20250228 LYD VKU AI Blended-Learning.pptx
Machine Learning_overview_presentation.pptx
The AUB Centre for AI in Media Proposal.docx
Empathic Computing: Creating Shared Understanding
Assigned Numbers - 2025 - Bluetooth® Document
sap open course for s4hana steps from ECC to s4
Encapsulation theory and applications.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Dropbox Q2 2025 Financial Results & Investor Presentation

Pointless Pointers - How to make our interfaces efficient?

  • 1. Mateusz Pusz November 15, 2017 POINTLESS POINTERS HOW TO MAKE OUR INTERFACES EFFICIENT?
  • 2. code::dive 2017 | Pointless Pointers WHAT IS A POINTER? 2
  • 3. A pointer is a programming language data type whose value refers directly to (or "points to") another value stored elsewhere in the computer memory using its address. -- Wikipedia code::dive 2017 | Pointless Pointers WHAT IS A POINTER? 2
  • 4. code::dive 2017 | Pointless Pointers WHAT IS A POINTER? 3
  • 5. Pointers due to their ambiguous nature are the source of most problems and bugs in C++ code. Lack of understanding between code architect and the user results in crashes, asserts and memory leaks!!! -- Mateusz Pusz ☺ code::dive 2017 | Pointless Pointers WHAT IS A POINTER? 3
  • 6. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO 4
  • 7. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference 4
  • 8. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks 4
  • 9. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks Bu er Overflows 4
  • 10. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks Bu er Overflows Hangs! 4
  • 11. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks Bu er Overflows Hangs! Crashes! 4
  • 12. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks Bu er Overflows Hangs! Crashes!Stability!!! 4
  • 13. code::dive 2017 | Pointless Pointers POINTERS MISUSE LEADS TO Null Pointer Dereference Resource leaks Bu er Overflows Hangs! Crashes!Stability!!! Security!!! 4
  • 14. B* a(A* ptr) { /* ... */; return b(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 15. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 16. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } B* c(A* ptr) { /* ... */; return d(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 17. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } B* c(A* ptr) { /* ... */; return d(ptr); } B* d(A* ptr) { /* ... */; return e(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 18. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } B* c(A* ptr) { /* ... */; return d(ptr); } B* d(A* ptr) { /* ... */; return e(ptr); } B* e(A* ptr) { /* ... */; return f(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 19. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } B* c(A* ptr) { /* ... */; return d(ptr); } B* d(A* ptr) { /* ... */; return e(ptr); } B* e(A* ptr) { /* ... */; return f(ptr); } B* f(A* ptr) { /* ... */; return g(ptr); } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 20. B* a(A* ptr) { /* ... */; return b(ptr); } B* b(A* ptr) { /* ... */; return c(ptr); } B* c(A* ptr) { /* ... */; return d(ptr); } B* d(A* ptr) { /* ... */; return e(ptr); } B* e(A* ptr) { /* ... */; return f(ptr); } B* f(A* ptr) { /* ... */; return g(ptr); } B* g(A* ptr) { /* ... */; return *ptr; } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 5
  • 21. B* a(A* ptr) { /* ... */; assert(ptr); return b(ptr); } B* b(A* ptr) { /* ... */; assert(ptr); return c(ptr); } B* c(A* ptr) { /* ... */; assert(ptr); return d(ptr); } B* d(A* ptr) { /* ... */; assert(ptr); return e(ptr); } B* e(A* ptr) { /* ... */; assert(ptr); return f(ptr); } B* f(A* ptr) { /* ... */; assert(ptr); return g(ptr); } B* g(A* ptr) { /* ... */; assert(ptr); return *ptr; } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 6
  • 22. B* a(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return b(ptr); } B* b(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return c(ptr); } B* c(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return d(ptr); } B* d(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return e(ptr); } B* e(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return f(ptr); } B* f(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return g(ptr); } B* g(A* ptr) { /* ... */; if(!ptr) throw std::invalid_argument{""}; return *ptr; } code::dive 2017 | Pointless Pointers PROBLEM DEFINITION 7
  • 23. B* func(A* arg); code::dive 2017 | Pointless Pointers QUIZ - GUESS WHAT? 8
  • 24. person* add(name* n); code::dive 2017 | Pointless Pointers QUIZ - GUESS WHAT? 9
  • 25. person* add(name* n); code::dive 2017 | Pointless Pointers QUIZ - GUESS WHAT? Is it better now? Is it enough? Do you know how to use that function? Do you know how to implement that function? 9
  • 26. person* add(name* n); void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #1 10
  • 27. person* add(name* n); void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #1 Is that a valid usage of add() interface? What are potential problems with above code? 10
  • 28. person* add(name* n); void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #2 11
  • 29. person* add(name* n); void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #2 Is that a valid usage of add() interface? 11
  • 30. person* add(name* n); void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #3 12
  • 31. person* add(name* n); void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #3 Is that a valid usage of add() interface? What are potential problems with above code? 12
  • 32. person* add(name* n); void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #4 13
  • 33. person* add(name* n); void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers ADD() USAGE – TAKE #4 Is that a valid usage of add() interface? What are potential problems with above code? 13
  • 34. void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers 1 2 3 4 WHICH ONE IS CORRECT? 14
  • 35. void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers 1 2 3 4 QUIZ - MATCH IMPLEMENTATION std::deque<person> people; person* add(name* n) { people.emplace_back((n != nullptr) ? *n : "anonymous"); return &people.back(); } 15
  • 36. void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers QUIZ - MATCH IMPLEMENTATION 1 void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } 2 3 4 person* add(name* n) { assert(n); int num = 0; for(auto ptr = n; *ptr != ""; ++ptr) ++num; person* p = new person[num]; for(auto i = 0; i<num; ++i) p[i].name(n[i]); return p; } 16
  • 37. void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } code::dive 2017 | Pointless Pointers QUIZ - MATCH IMPLEMENTATION 1 void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } 2 3 void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } 4 person* add(name* n) { assert(n != nullptr); return new person{n}; } 17
  • 38. void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } code::dive 2017 | Pointless Pointers QUIZ - MATCH IMPLEMENTATION void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } 1 2 3 void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } 4 std::deque<person> people; person* add(name* n) { if(n == nullptr) return nullptr; auto it = find_if(begin(people), end(people), [&](person& p) { return p.name() == *n; }); if(it != end(people)) return nullptr; people.emplace_back(*n); return &people.back(); } 18
  • 39. code::dive 2017 | Pointless Pointers QUIZ - MATCH IMPLEMENTATION void foo() { person* p = add(new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } 1 2 3 4 19
  • 40. person* add(name* n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 20
  • 41. person* add(name* n); std::unique_ptr<person> add(std::unique_ptr<name> n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 20
  • 42. person* add(name* n); std::unique_ptr<person> add(std::unique_ptr<name> n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? Do you know how to use that function? Do you know how to implement that function? 20
  • 43. person* add(name* n) { assert(n != nullptr); return new person{n}; } void foo() { person* p = add( new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #1 21
  • 44. void foo() { auto p = add( std::make_unique<name>("Mateusz Pusz")); assert(p != nullptr); process(p->id(), p->name()); } std::unique_ptr<person> add(std::unique_ptr<name> n) { assert(n != nullptr); return std::make_unique<person>(std::move(n)); } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #1 person* add(name* n) { assert(n != nullptr); return new person{n}; } void foo() { person* p = add( new name{"Mateusz Pusz"}); assert(p != nullptr); process(p->id(), p->name()); delete p; } 21
  • 45. person* add(name* n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 22
  • 46. person* add(name* n); person& add(std::optional<name> n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 22
  • 47. person* add(name* n); person& add(std::optional<name> n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? Do you know how to use that function? Do you know how to implement that function? 22
  • 48. std::deque<person> people; person* add(name* n) { people.emplace_back( (n != nullptr) ? *n : "anonymous"); return &people.back(); } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #2 23
  • 49. std::deque<person> people; person& add(std::optional<name> n) { people.emplace_back( n ? std::move(*n) : "anonymous"); return people.back(); } void foo() { person& p = add(name{"Mateusz Pusz"}); process(p.id(), p.name()); } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #2 std::deque<person> people; person* add(name* n) { people.emplace_back( (n != nullptr) ? *n : "anonymous"); return &people.back(); } void foo() { name n{"Mateusz Pusz"}; person* p = add(&n); if(p != nullptr) process(p->id(), p->name()); } 23
  • 50. person* add(name* n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 24
  • 51. person* add(name* n); std::tuple<person&, bool> add(name n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 24
  • 52. person* add(name* n); std::tuple<person&, bool> add(name n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? Do you know how to use that function? Do you know how to implement that function? 24
  • 53. std::deque<person> people; person* add(name* n) { if(n == nullptr) return nullptr; auto it = find_if( begin(people), end(people), [&](person& p) { return p.name() == *n; }); if(it != end(people)) return nullptr; people.emplace_back(*n); return &people.back(); } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #3 25
  • 54. std::deque<person> people; std::tuple<person&, bool> add(name n) { auto it = find_if( begin(people), end(people), [&](person& p) { return p.name() == n; }); if(it != end(people)) return { *it, false }; people.emplace_back(std::move(n)); return { people.back(), true }; } void foo() { auto r = add(name{"Mateusz Pusz"}); if(std::get<bool>(r)) process(std::get<0>(r).id(), std::get<0>(r).name()); } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #3 std::deque<person> people; person* add(name* n) { if(n == nullptr) return nullptr; auto it = find_if( begin(people), end(people), [&](person& p) { return p.name() == *n; }); if(it != end(people)) return nullptr; people.emplace_back(*n); return &people.back(); } void foo() { name* n = new name{"Mateusz Pusz"}; person* p = add(n); if(p != nullptr) process(p->id(), p->name()); delete n; } 25
  • 55. person* add(name* n); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 26
  • 56. person* add(name* n); std::vector<person> add(std::vector<name> names); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? 26
  • 57. person* add(name* n); std::vector<person> add(std::vector<name> names); code::dive 2017 | Pointless Pointers IS THERE A BETTER SOLUTION? Do you know how to use that function? Do you know how to implement that function? 26
  • 58. person* add(name* n) { assert(n); int num = 0; for(auto ptr = n; *ptr != ""; ++ptr) ++num; person* p = new person[num]; for(auto i = 0; i<num; ++i) p[i].name(n[i]); return p; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #4 27
  • 59. std::vector<person> add(std::vector<name> names) { std::vector<person> p; p.reserve(names.size()); for(auto& n : names) p.emplace_back(std::move(n)); return p; } void foo() { auto people = add({"Mateusz Pusz", "Jan Kowalski"}); for(auto& p : people) process(p.id(), p.name()); } code::dive 2017 | Pointless Pointers USING C++ THE RIGHT WAY – CASE #4 person* add(name* n) { assert(n); int num = 0; for(auto ptr = n; *ptr != ""; ++ptr) ++num; person* p = new person[num]; for(auto i = 0; i<num; ++i) p[i].name(n[i]); return p; } void foo() { name names[] = {"Mateusz Pusz", "Jan Kowalski", ""}; person* people = add(names); assert(people != nullptr); for(int i=0; i<sizeof(names)/sizeof(*names) - 1; ++i) process(people[i].id(), people[i].name()); delete[] people; } 27
  • 61. ARGUMENT TYPE POINTER ARGUMENT DECLARATION Mandatory big value void foo(A* in); Output function argument void foo(A* out); Array void foo(A* array); Optional value void foo(A* opt); Ownership passing void foo(A* ptr); code::dive 2017 | Pointless Pointers POINTERS USAGE IN ANSI C 29
  • 62. ARGUMENT TYPE POINTER ARGUMENT DECLARATION Mandatory big value void foo(A* in); Output function argument void foo(A* out); Array void foo(A* array); Optional value void foo(A* opt); Ownership passing void foo(A* ptr); code::dive 2017 | Pointless Pointers POINTERS USAGE IN ANSI C Pointer ambiguity makes it really hard to understand the intent of the interface author. 29
  • 63. ARGUMENT TYPE POINTER ARGUMENT DECLARATION Mandatory big value void foo(const A& in); Output function argument A foo(); or std::tuple<...> foo(); or void foo(A& out); Array void foo(const std::vector<A>& a); Optional value void foo(std::optional<A> opt); or void foo(A* opt); Ownership passing void foo(std::unique_ptr<A> ptr); code::dive 2017 | Pointless Pointers DOING IT C++ WAY 30
  • 64. ARGUMENT TYPE POINTER ARGUMENT DECLARATION Mandatory big value void foo(const A& in); Output function argument A foo(); or std::tuple<...> foo(); or void foo(A& out); Array void foo(const std::vector<A>& a); Optional value void foo(std::optional<A> opt); or void foo(A* opt); Ownership passing void foo(std::unique_ptr<A> ptr); code::dive 2017 | Pointless Pointers DOING IT C++ WAY Use above Modern C++ constructs to explicitly state your design intent. 30
  • 65. B foo(std::optional<A> arg); const A& foo(const std::array<A, 3>& arg); std::unique_ptr<B> foo(A arg); std::vector<B> foo(const A& arg); code::dive 2017 | Pointless Pointers QUIZ – GUESS WHAT? 31
  • 66. int count_lower(const char* ptr, size_t size); void add_2(int* ptr, size_t size); code::dive 2017 | Pointless Pointers C++17 AND C++20: WHAT ABOUT POINTER AND A SIZE ANSI C -> C++14 ANSI C -> C++14 32
  • 67. int count_lower(const char* ptr, size_t size); void add_2(int* ptr, size_t size); int count_lower(std::string_view txt); void add_2(std::span<int> array); code::dive 2017 | Pointless Pointers C++17 AND C++20: WHAT ABOUT POINTER AND A SIZE ANSI C -> C++14 ANSI C -> C++14 C++17 C++20 32
  • 69. C++ is a powerful tool: • strong type system • better abstractions • templates • C++ STD library code::dive 2017 | Pointless Pointers C++ IS NOT ANSI C!!! 34