CSE333(9-11): C++ Intro
CSE333 is a good course.
Lecture 9: Low-Level I/O – the POSIX Layer
Your program can access many layers of APIs:
- C standard library
- Some are just ordinary functions (<string.h>, for example)
- Some also call OS-level (POSIX) functions (<stdio.h>, for example)
- POSIX compatibility API
- C-language interface to OS system calls (fork(), read(), etc.)
- Underlying OS system calls
- Assembly language
C Standard Library File I/O
- So far you’ve used the C standard library to access files
- Use a provided FILE* stream abstraction
- fopen(), fread(), fwrite(), fclose(), fseek()
- These are convenient and portable
- They are buffered
- They are implemented using lower-level OS calls
Lower-Level File Access
Most UNIX-en support a common set of lower-level file access APIs: POSIX – Portable Operating System Interface
- open(), read(), write(), close(), lseek()
- Similar in spirit to their
f*()
counterparts from C std lib - Lower-level and unbuffered compared to their counterparts
- Also less convenient
- Similar in spirit to their
- We will have to use these to read file system directories and for network I/O, so we might as well learn them now
open()/close()
To open a file:
- Pass in the filename and access mode
- Similar to fopen()
- Get back a “file descriptor”
- Similar to FILE* from fopen(), but is just an int
- Defaults: 0 is stdin, 1 is stdout, 2 is stderr
#include <fcntl.h> // for open()
#include <unistd.h> // for close()
...
int fd = open("foo.txt", O_RDONLY);
if (fd == -1) {
perror("open failed");
exit(EXIT_FAILURE);
}
...
close(fd);
Reading from a File
ssize_t read(int fd, void* buf, size_t count);
- Returns the number of bytes read
- Might be fewer bytes than you requested (!!!)
- Returns 0 if you’re already at the end-of-file
- Returns -1 on error
- read has some surprising error modes…
- On error, read returns -1 and sets the global
errno
variable - You need to check
errno
to see what kind of error happened - EBADF: bad file descriptor
- EFAULT: output buffer is not a valid address
- EINTR: read was interrupted, please try again
- On error, read returns -1 and sets the global
Low-level functions
- creat(), open(), close() – managing I/O channels
- read(), write() – handling input and output operations
- lseek() – for random access of files
- link(), unlink() – aliasing and removing files
- stat() – getting file status
- access(), chmod(), chown() – for access control
- exec(), fork(), wait(), exit() — for process control
- getuid() – for process ownership
- getpid() – for process ID
- signal() , kill(), alarm() – for process control
- chdir() – for changing working directory
- mmap(), shmget(), mprotect(), mlock() – manipulate low level memory attributes
- time(), gettimer(), settimer(),settimeofday(), alarm() – time management functions
- pipe() – for creating inter-process communication
Lecture 10 - C++ Intro
C++ Pros
A major addition is support for classes and objects!
- Classes
- Public, private, and protected methods and instance variables
- (multiple!) inheritance
- Polymorphism
- Static polymorphism: multiple functions or methods with the same name, but different argument types (overloading)
- Works for all functions, not just class members
- Dynamic (subtype) polymorphism: derived classes can override methods of parents, and methods will be dispatched correctly
- Supports templates to facilitate generic data types
- Permits a module to define its own namespace
- Classes also allow duplicate names without collisions
- Entire C++ standard library is in a namespace std
- The C++ standard library is huge
- Supports exceptions to handle error
- Many Features
- Operator Overloading
- Object constructors, destructors
- Reference Types
- Advanced Objects
- iomanip
C++ Cons
-
No Garbage Collector: need to track ownership of memory, but Smart pointers and Resource Allocation Is Initialization(RAII) will help
-
Smart Pointer
- Classes that encapsulate pointers and track reference counts
- Deallocate memory when the reference count goes to zero
-
RAII
- Useful for releasing memory, locks, database transactions, and more
Lecture 11 - C++ References, Const, Classes
Pointers work in same in C and C++
References
A reference is an alias for another variable, introduced in C++.
int x = 5;
int& z = x; // binds the name 'z' to x
In this way, both x and z will point to the address that stores 5.
- C++ allows you to use real pass-by-reference
- Client passes in an argument with normal syntax
- Function uses reference parameters with normal syntax
- Modifying a reference parameter modifies the caller’s argument
const
- Signal of intent to compiler; meaningless at hardware level
- Results in compile-time errors
- const next to pointer name means you can’t change the value of the pointer
- const next to data type pointed to means you can’t use this pointer to change the thing being pointed to
const and Pointers
Tip: read variable declaration from right-to-left
int main(int argc, char** argv) {
int x = 5; // int
const int y = 6; // (const int)
y++; // compiler error
const int *z = &y; // pointer to a (const int)
*z += 1; // compiler error
z++; // ok
int *const w = &x; // (const pointer) to a (variable int)
*w += 1; // ok
w++; // compiler error
const int *const v = &x; // (const pointer) to a (const int)
*v += 1; // compiler error
v++; // compiler error
return EXIT_SUCCESS;
}
Google Style Guide Convention
- Use const references or call-by-value for input values
- Particularly for large values (no copying)
- Use pointers for output parameters
- List input parameters first, then output parameters last
void CalcArea(const int& width, const int& height, int* const area) {
*area = width * height;
}
int main(int argc, char** argv) {
int w = 10, h = 20, a;
CalcArea(w, h, &a);
return EXIT_SUCCESS;
}
Google C++ style guide suggests:
- Input parameters:
- Either use values (for primitive types like int or small structs/objects)
- Or use
const
references (for complex struct/object instances)
- Output parameters:
- Use
const
pointers - Unchangeable pointers referencing changeable data
- Use
Classes
- Class definition syntax (in a .h file):
- Members can be functions (methods) or data (variables)
class Name {
public:
// public member declarations & definitions go here
private:
// private member delarations & definitions go here
}; // class Name
- Class member function definition syntax (in a .cc file):
- define within the class definition, or
- declare within the class definition and then define elsewhere
retType Name::MethodName(type1 param1, …, typeN paramN) {
// body statements
}
Class Definition (.h file)
#ifndef _POINT_H_
#define _POINT_H_
class Point {
public:
Point(const int x, const int y); // constructor
int get_x() const { return x_; } // inline member function
int get_y() const { return y_; } // inline member function
double Distance(const Point& p) const; // member function
void SetLocation(const int x, const int y); // member function
private:
int x_; // data member
int y_; // data member
}; // class Point
#endif // _POINT_H_
Class Member Definition (.cc file)
#include <cmath>
#include "Point.h"
Point::Point(const int x, const int y) {
x_ = x;
this->y_ = y; // "this->" is optional unless name conflicts
}
double Point::Distance(const Point& p) const {
// We can access p’s x_ and y_ variables either through the
// get_x(), get_y() accessor functions or the x_, y_ private
// member variables directly, since we’re in a member
// function of the same class.
double distance = (x_ - p.get_x()) * (x_ - p.get_x());
distance += (y_ - p.y_) * (y_ - p.y_);
return sqrt(distance);
}
void Point::SetLocation(const int x, const int y) {
x_ = x;
y_ = y;
}
Class Usage (.cc file)
#include <iostream>
#include "Point.h"
using namespace std;
int main(int argc, char** argv) {
Point p1(1, 2); // allocate a new Point on the Stack
Point p2(4, 6); // allocate a new Point on the Stack
cout << "p1 is: (" << p1.get_x() << ", ";
cout << p1.get_y() << ")" << endl;
cout << "p2 is: (" << p2.get_x() << ", ";
cout << p2.get_y() << ")" << endl;
cout << "dist : " << p1.Distance(p2) << endl;
return 0;
}
Today, review C++, and know more about C++. good.