9. Inline Functions - Egloospds16.egloos.com/pds/200911/25/21/Chapter_9_1.pdf · Thinking in C++...
Transcript of 9. Inline Functions - Egloospds16.egloos.com/pds/200911/25/21/Chapter_9_1.pdf · Thinking in C++...
9. Inline Functions9. Inline Functions
김동원김동원김동원김동원
2003.04.02
Thinking in C++ Page 1
Overview
• Preprocessor pitfalls
• Inline functions
• Stash & Stack with inlines
Thinking in C++ Page 2
• Two problems preprocessor macros in C++– C : A macro looks like a function call - difficult-to-find bugs
– C++ : The preprocessor has no permission to access private data,
Preprocessor macros cannot be used as class member functions
• Expressions may expand inside the macro– #define F (x) (x + 1)
– #define FLOOR(x,b) x>=b?0:1
if(FLOOR(a&0x0f,0x07)) // ...
if(a&0x0f>=0x07?0:1)
- #define FLOOR(x,b) ((x)>=(b)?0:1)
• Every time you use an argument in a macro, that argument is evaluated
Preprocessor pitfalls
Thinking in C++ Page 3
//: C09:MacroSideEffects.cpp
#include "../require.h"
#include <fstream>
using namespace std;
#define BAND(x) (((x)>5 && (x)<10) ? (x) : 0)
int main() {
ofstream out("macro.out");
assure(out, "macro.out");
for(int i = 4; i < 11; i++) {
int a = i;
out << "a = " << a << endl << '\t';
out << "BAND(++a)=" << BAND(++a) << endl;
out << "\t a = " << a << endl;
}
} ///:~
a = 4
BAND(++a)=0
a = 5
a = 5
BAND(++a)=8
a = 8
a = 6
BAND(++a)=9
a = 9
a = 7
BAND(++a)=10
a = 10
a = 8
BAND(++a)=0
a = 10
a = 9
BAND(++a)=0
a = 11
a = 10
BAND(++a)=0
a = 12
Preprocessor pitfalls (example)
Thinking in C++ Page 4
Preprocessor pitfalls
• Macros and access
- A macro has no concept of the scoping required with member functions
class X {
int i;
public:
#define VAL(X::i) // Error
Thinking in C++ Page 5
Inline functions
• Inline Functions
- In solving the C++ problem of a macro with access to private class members
- Any behavior you expect from an ordinary function
- Inline function is expanded in place, like a preprocessor macro, so the overhead of the function call is eliminated
- Any function defined within a class body is automatically inline
- Non-class function inline by preceding it with the inline keyword
Thinking in C++ Page 6
Inline functions (2)
- you must include the function body with the declaration
� inline int plusOne(int x);
� inline int plusOne(int x) { return ++x; }
Thinking in C++ Page 7
Inline functions (3)
· Inlines inside classes
- Any function you define inside a class definition is automatically an inline
- The logical behavior of a function must be identical regardlessof whether it's an inline
- The only difference you'll see is in performance
Thinking in C++ Page 8
Inlines inside classes (example)
//: C09:Inline.cpp
// Inlines inside classes
#include <iostream>
#include <string>
using namespace std;
class Point {
int i, j, k;
public:
Point(): i(0), j(0), k(0) {}
Point(int ii, int jj, int kk)
: i(ii), j(jj), k(kk) {}
Thinking in C++ Page 9
Inlines inside classes (example)
void print(const string& msg = "") const {
if(msg.size() != 0) cout << msg << endl;
cout << "i = " << i << ", "
<< "j = " << j << ", "
<< "k = " << k << endl;
}
};
int main() {
Point p, q(1,2,3);
p.print("value of p");
q.print("value of q");
} ///:~
Thinking in C++ Page 10
Inline functions
• Access Functions
– uses of Inlines inside classes is the access function
//: C09:Access.cpp
// Inline access functions
class Access {
int i;
public:
int read() const { return i; }
void set(int ii) { i = ii; }
};
int main() {
Access A;
A.set(100);
int x = A.read();
} ///:~
Thinking in C++ Page 11
• Accessors and Mutators
- Accessors : to read state information from an object
- Mutators : to change the state of an object
- Function overloading Instead to use "get" and "set" to indicate accessors and mutators
- Time class
Inline functions
Thinking in C++ Page 12
Access functions (example)
class Access {
int i;
public:
int read() const { return i; }
void set(int ii) { i = ii; }
};
int main() {
Access A;
A.set(100);
int x = A.read();
} ///:~
Thinking in C++ Page 13
Accessors and mutators (example)
//: C09:Rectangle.cpp
// Accessors & mutators
class Rectangle {
int wide, high;
public:
Rectangle(int w = 0, int h = 0)
: wide(w), high(h) {}
int width() const { return wide; } // Read
void width(int w) { wide = w; } // Set
int height() const { return high; } // Read
void height(int h) { high = h; } // Set
};
int main() {
Rectangle r(19, 47);
// Change width & height:
r.height(2 * r.width());
r.width(2 * r.height());
} ///:~
Thinking in C++ Page 14
Accessors and mutators (example)
//: C09:Rectangle2.cpp
// Accessors & mutators with "get" and "set"
class Rectangle {
int width, height;
public:
Rectangle(int w = 0, int h = 0)
: width(w), height(h) {}
int getWidth() const { return width; }
void setWidth(int w) { width = w; }
int getHeight() const { return height; }
void setHeight(int h) { height = h; }
};
int main() {
Rectangle r(19, 47);
// Change width & height:
r.setHeight(2 * r.getWidth());
r.setWidth(2 * r.getHeight());
} ///:~
Thinking in C++ Page 15
Stash & Stack with inlines (example)
//: C07:Stash3.h
#ifndef STASH3_H
#define STASH3_H
class Stash {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
// Dynamically allocated array of bytes:
unsigned char* storage;
void inflate(int increase);
public:
Stash(int size); // Zero quantity
Stash(int size, int initQuantity);
~Stash();
int add(void* element);
void* fetch(int index);
int count();
};
#endif // STASH3_H ///:~
Thinking in C++ Page 16
Stash & Stack with inlines (example)
// Inline functions
#ifndef STASH4_H
#define STASH4_H
#include "../require.h"
class Stash {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
// Dynamically allocated array of bytes:
unsigned char* storage;
void inflate(int increase);
public:
Stash(int sz) : size(sz), quantity(0),
next(0), storage(0) {}
Stash(int sz, int initQuantity) : size(sz),
quantity(0), next(0), storage(0) {
inflate(initQuantity);
}
Thinking in C++ Page 17
Stash & Stack with inlines (example)
Stash::~Stash() {
if(storage != 0)
delete []storage;
}
int add(void* element);
void* fetch(int index) const {
require(0 <= index, "Stash::fetch (-)index");
if(index >= next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(storage[index * size]);
}
int count() const { return next; }
};
#endif // STASH4_H ///:~
Thinking in C++ Page 18
Stash & Stack with inlines (example)
//: C06:Stack3.h
// With constructors/destructors
#ifndef STACK3_H
#define STACK3_H
class Stack {
struct Link {
void* data;
Link* next;
Link(void* dat, Link* nxt);
~Link();
}* head;
public:
Stack();
~Stack();
void push(void* dat);
void* peek();
void* pop();
};
#endif // STACK3_H ///:~
Thinking in C++ Page 19
Stash & Stack with inlines (example)
//: C09:Stack4.h
// With inlines
#ifndef STACK4_H
#define STACK4_H
#include "../require.h"
class Stack {
struct Link {
void* data;
Link* next;
Link(void* dat, Link* nxt):
data(dat), next(nxt) {}
}* head;
public:
Stack() : head(0) {}
~Stack() {
require(head == 0, "Stack not empty");
}
Thinking in C++ Page 20
Stash & Stack with inlines (example)
void push(void* dat) {
head = new Link(dat, head);
}
void* peek() const {
return head ? head->data : 0;
}
void* pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
};
#endif // STACK4_H ///:~