Object-Oriented Data Structures in C++ (3)
Summary
- study lifecycle cpp object by taking coursera class.
- lecture
- https://www.coursera.org/learn/cs-fundamentals-1/home/week/3
- if you want to take this class, you should sign up/in coursera.
- keyword
- Constructors and Destructors
- Methods and Operators
- Access through pointers and references
Lecture
3.1 Class Constructors
- Automatic Default Constructor
- Every class we’ve seen so far has a constructor.
- It initialize all member variables to their default values.
- Custom Default Constructor
- The simplest constructor.
- It specifies the state of the object when the object is constructed.
- A member function with the same name of the class, taking zero parameters and no return type.
- Custom Constructors
- more fancy than default constructors.
- allow user code to specify arguments.
- If any custom constructor is defined, an automatic default constructor is not defined.
3.2 Copy Constructors
- Automatic Copy Constructor
- If you don’t write custom copy constructor, c++ compiler provides an automatic copy constructor for your class.
- It can copy the contents of all member variables.
- Custom Copy Constructor
- It has exactly one argument.
- The argument must be const reference of the same type as the class.
Cube::Cube(const Cube &obj)
- The argument must be const reference of the same type as the class.
- Copy Constructor Invoke
- Constructor Example
Cube() { std::cout << "default constructor invoked!" << std::endl; } Cube(const Cube & obj) { std::cout<< "copy constructor invoked!" << std::endl; }
- Example 1
- Code
void test(Cube cube) { // Nothing } int main() { Cube c; test(c); // copy the obj through 'test' function. return 0; }
- Result
default constructor invoked! copy constructor invoked!
- Code
- Example 2
- Code
Cube test() { Cube c; return c; // copy1 } int main() { Cube c2 = test(); // copy2 return 0; }
- Result
default constructor invoked! copy constructor invoked! copy constructor invoked!
- Code
- Example 3
- Code
int main() { Cube c; Cube myCube = c; }
- Result
default constructor invoked! copy constructor invoked!
- Code
- Example 4
- Code
int main() { Cube c; Cube myCube; myCube = c; }
- Result
default constructor invoked! default constructor invoked!
- They’ve already been created by default constructor.
- A constructor’s job is to actually create the object itself.
- we’re just doing copying. (assignment)
- So, there’s no copy constructor.
- Code
- Constructor Example
- It has exactly one argument.
3.3 Copy Assignment Operator
- Custom Assignment Operator
Cube & operator=(const Cube &obj)
- It is a public function of the Class.
- It has the name “operator=”
- It has a return value of reference of class type.
- It has exactly one argument
3.4 Variable Storage
- Every variables are stored …
directly in memory, accessed via a pointer, or accessed by a reference.
- Direct Storage
- The type, size of a variable has no modifiers.
- Storage by Pointer
- The type of a variable is modified with an asterisk (*).
- A pointer takes a “memory address width” of memory. (by your system)
- The pointer “points” to the allocated space of the object.
- Storage by Reference
- A reference is a special type of variable which aliases existing memory by name.
- A reference does not store memory itself(It takes zero bytes of memory to create a reference variable), it is only an alias to another variable.
- It is denoted by the type with an ampersand(&).
3.5 Class Destructor
- very last call in the class’s lifecycle when an instance of class is cleaned up.
Automatic Default Destructor
- It is added to your class if no other destructor is defined.
- It call the default destructor of all member objects.
- It never be called directly. Instead, it is automatically called when the object’s memory is being reclaimed by the system.
- if the object is on the stack, when the function returns(end).
- if the object is on the heap, when delete is used.
Custom Destructor
- A custom destructor is a member function.
- It has the name of the class it self. and is preceded by a tilde (~).
- All destructor has no argument and no return type.
Custom_Destructor::~Custom_Destructor();
- It is essential when an object allocates an external resource that must be closed or freed when the object is destroyed.
- Heap memory
- Open files
- Shared Memory
Reading
C++ Syntax Notes: Uninitialized Pointer, Segfault, Undefined Behavior
- Segfault
- If you dereference an memory access that you shouldn’t, this is often called ‘segmentation fault’ or ‘segfault’
#include<iostream> using namespace std; char *c = nullptr cout << c << endl;
- If you dereference an memory access that you shouldn’t, this is often called ‘segmentation fault’ or ‘segfault’
- Undefined Behavior
- https://www.secmem.org/blog/2020/01/17/c-c++-and-ub/
- Reset ‘nullptr’ after ‘delete’ memory
int *i = new int; // allocate an integer memory on the heap. // now i holds some memory address to a valid integer. *i = 10; // do some work with integer. delete i; // this destroys the integer on the heap and frees the memory. // but i still holds the memory address. i = nullptr; // so, set i to nullptr for safety.
C++ Syntax Notes: The Modern Ranged-Based “for” loop
- you can use “for loop” in this way.
for {temporaray variable declaration: container} { // loop body }
- there are three ways about usage of “for loop”
- use temporary value by copy
- use temporary value of reference type
- use value of const reference type
- use temporary value by copy
- following for loop makes a temporary copy each vector item by value.
- Since variable “i” is just a temporary copy, any changes to “i” do not modify the actual container.
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (int i : v) { i = 100; } for (int i : v) { cout << "member : " << i << endl; } } /* member : 1 member : 2 member : 3 */
- use temporary value of reference type
- If you make the temporary variable of reference type, you can modify the actual container item.
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (int &i:v) { i = 100; } for (int i:v) { cout << "member: "<< i << endl; } } /* member: 100 member: 100 member: 100 */
- If you make the temporary variable of reference type, you can modify the actual container item.
- use value of const reference type
- This verson uses a reference, so it doesn’t make any copies.
- However, following is read-only since the const mark.
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (const int &i:v) { i = 100; } for (int i:v) { cout << "member: "<< i << endl; } } /* test.cpp:10:5: error: cannot assign to variable 'i' with const-qualified type 'const int &' i = 100; ~ ^ */
Unsigned Integer Types
Graded Activities
Quiz
Challenge
- implement single, copy constructor with shallow copy and deep copy.
- implement destructor.
class Test() { public: int *ta, *tb; Test(int, int); Test(const Test &); ~Test(); }; Test::Test(int a, int b) { // ta points a, tb points b. Pointer points just each local variable. ta = new int(a); tb = new int(b); } Test::Test(const Test &tc) { // tc is alias. ta = new int(*(tc.ta)); tb = new int(*(tc.tb)); } Test::~Test() { delete ta; delete tb; } int main() { Test t(1,2); // Test(int, int) is invoked! Test t2(t); // Test(const Test&) is invoked! deep copy. Test *t3 = new Test(3,4); // Test(int, int) is invoked! delete t3; // ~Test() is invoked! return 0; }