All about cpp

5 minute read

Week 1

Wed

  • community: #include <c++>
  • quick links:
  • const
    • auto const course_code = std:string("COMP6771") The whole string is constant
    • If the const is on string builder, the string that is appended everytime is constant
    • const is always on the right
  • string comparision and assignment
    • != to compare two string literal values not reference of string (unlike Java)
    • The slide mentions C++ value semantics

Thurs

  • The compiler we’re using: clang++-11 hello.cpp -o hello
  • clang++-11 -Wall -Wextra -pedantic -std=c++20 -stdlib=libc++ -o hello_test hello.cpp hello_test.cpp
  • This course is using CMake, clang-tidy. Chris had some demos on how to use the test framework in the first 30 mins of lecture
  • Type conversion
    • narrow(lossy) conversion, for example int => bool
  • Default arguments
    • std::string rgb(short r = 0, short g = 0, short b = 0);
  • Two librarys learnt:
    • https://github.com/gsl-lite/gsl-lite
    • https://github.com/abseil/abseil-cpp
  • We read backwards: a reference to a const integer i auto i = 1; auto const& ref = i;
  • benchmark library: https://github.com/google/benchmark
  • cpp reference &
    • Don’t need to use -> to access elements
    • Can’t be null
    • You can’t change what they refer to once set

Week 2 - need to be revisited

Wed

  • Iterator avoids losing track of container
    auto playing_card = ranges::find(hand, blue_number);
    REQUIRE(playing_card != hand.end());
    CHECK(*playing_card == blue_number);
    
    playing_card = hand.erase(playing_card); // we remove a card from our hand when we play it
    REQUIRE(playing_card != hand.end());
    CHECK(*playing_card == green_draw_two);
    
    The erase() function returns a new iterator to update the new position in the container. This is because when vector shrinks, the memory will change. If you don’t use the new iterator, the old one may point to null.
    auto playing_card = ranges::find(hand, blue_number);
    REQUIRE(playing_card != hand.end());
    CHECK(*playing_card == blue_number);
    
    hand.push_back(green_draw_two);
    card_to_play = ranges::find(hand, blue_number)
    
    Same reason as above. When vector expands, the memory will change. We need to re-find the element and the find() will return an updated new iterator.
  • erase function we saw in this course
    • vector.erase(iterator)
    • std::erase(vector, element)
  • Lambda function need to revisit!!

  • static program analysis: clang-tidy
  • link: just to understand iterator pattern

Thurs

  • More on vector: need to revisit later!!!

Week 3

Wed

  • copy constructor: given auto v2 = std::vector<int>{}
    • auto v3 = v2;
    • auto v3 = std::vector<int>(v2);
    • They are the same.
  • In a C++ class, if access modifier is not specified, the method is private by default.
  • Definition of class initialiser: double salary = 1200.5; in the class
  • There is a benefit of constructor initialiser list and uniform intialisation: Initialiser lists and uniform initialisation avoid having to construct an object once, and then reassign it to a different value after construction. It is more efficient, and for some types, you will not be able to compile without it.
    class person {
    public:
        person()
        : age_{99} { // This is ok!
            /* age_ = 20  (Compile Error!!) */
        }
        auto get_age() -> int const&;
    private:
        int const age_ = 18;
    };
    
    • If the private variable is defined in const auto const age_ = 18;, then the const value can be overwritten by constructor initialiser list but can’t be written by the assignment in the constructor.

Thurs

  • explicit keyword to disable implicit conversion.
  • const object can only call const method functions, but const method can be called in any object.
    • There is an exception: using mutable keyword
  • static auto valid_name(std::string const& name) -> bool is a static method in cpp.
    • Rule of thumb: you can use static method whenever that method doesn’t require any class variables.
  • static class variable
    • Rule of thumb: you may use it to define some constants associated with class for example std::string::npods.
  • inline static variable
  • copying constructor is a default thing that cpp compiler is able to do though the user doesn’t write the constructor with the copying paratemeter explicitly.
    auto a = intvec{}
    auto b = intvec{a}
    
  • intvec() = default defines default constructor. Note that intvec() is a constructor.
  • intvec() = delete It is to prevent copy constructor when it is called implicitly. For example, when the calling function has “passed-by-value” parameter.
  • friend will be used in operator+,-, *, /, %, <<-like operator overloading for example friend point operator+(point const& lhs, point const& rhs).
    • please put the friend operators implementation in class definition (header file)
    • Q: why we need to have friend ???
    • A: for example interface - friend method can cache the values the interface provides
  • Operator overloading - It is “overloading” so any return type and parameter type should be fine. However, it has special meaning to use reference or whether to be friend or object memeber. However, you can do anything doesn’t mean you should do anything.
  • for operator+=-like operator overloading for example
    point point::operator+=(point const& p) {
        x_ += p.x_;
        y_ += p.y_;
        return *this;
    }
    
    • It is class method because the current object this has meaning on it, whereas, operator+,-,*,/,%,<<-like, there is no current object involved and therefore, we use friend.
  • Miscs
    • [[nodiscard]] to let compiler give warnings if the return value from a function(struct) isn’t handled in the caller function.
    • A noexcept specification on a function is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.
      • car::~car() noexcept;

Week 4

Weds

  • hidden friend functions are functions defined inside class and regular friend functions are functions defined outside class.
  • assignment is p2 = p1 instead of auto p2 = p1. The latter one is doing copy constructor.
  • subscript operator overloading
    int operator[](int index) const {
        return index == 0 ? x_ : y_;
    }
    
    • This one is for p1[0]
    int& operator[] (int index) {
        return index == 0 ? x_ : y_;
    }
    
    • This one is for p1[0] = 100
  • Why we prefer static_cast? It’s because static_cast is written by programmer and it has clear error message. Otherwise it is compiler generating error message.
  • type conversion operator overloading: it is better to include explicit to force explicit conversion for type conversion operator overloading.
    explicit operator std::vector<int>() const {
    	return std::vector<int>{x_, y_};
    }
    
    • Below is the usage: implicit type conversion is not a good practise because of the behaviour of compiler.
      std::vector<int> vec = p; // implicit
      auto vec = std::vector<int>(p); // explicit
      auto vec = static_cast<std::vector<int>>(p); // explicit
      
  • Compiler Explorer options: x86-64 clang(trunk) -std=c++20 -stdlib=libc++

To explore more later:

tute questions not covered

  • tut01, 02, 03Q1-Q3