C++(98/11)问题 (2)

多线程问题(续)

线程可以独立运行,但是同时又和同进程的其他线程共享资源,这就造成在需要获取共同资源的时候需要竞争对于资源的使用,所有的关于线程的使用都是在设计如何竞争环境下使用共同的资源,以及更高效的问题

线程之间共享数据

  • 互斥量 std::mutex,对于mutex的变量有lock和unlock来控制。此外,还有lock_guard来在构造锁定 析构是解锁。
std::list some_list;
std::mutex some_mutex;

void add_to_list(int new_value)
{
    std::lock_guard guard(some_mutex);
    some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
    std::lock_guard guard(some_mutex);
    return std::find(some_list.begin(),some_list.end(),value_to_find)
        != some_list.end();
}

main


int main()
{
    add_to_list(4);
    std::cout<<"contains(1)="< answer = std::async(fun1);
    fun2();
    std::cout<

ex2

#include 
#include 
#include        
#include      
#include         
#include       //  accumulate

using namespace std;
void accumulat( vector::iterator first,
     vector::iterator last,
     promise &accumulate_promise)
{
    int sum =  accumulate(first, last, 0);
    accumulate_promise.set_value(sum);  // Notify future
}

int main(int argc, char *argv[])
{
    try {
         vector numbers = { 1, 2, 3, 4, 5, 6 };
         promise accumulate_promise;
         future accumulate_future = accumulate_promise.get_future();
         thread work_thread(accumulat, numbers.begin(), numbers.end(), ref(accumulate_promise));
        //accumulate_future.wait();  
         cout << "result = " << accumulate_future.get() << '\n';
        work_thread.join();  // wait for thread completion
    }
    catch ( exception &e)
    {
         cerr << e.what();
    }
    return 0;
}

内存模型

  • 对同一段内存修改的未定义行为
  • atomic原子类型的存储 memory order问题
    store
    load
    读写顺序模型

atomic类型的操作:
除了一组通常的操作(load()、store()、exchange()、compare_exchange_weak()和compare_exchange_strong())之外,像std::atomic或者std::atomic这样的原子整型还有相当广泛的一组操作可用:fetch_add()、fetch_sub()、fetch_and()、fetch_or()、fetch_xor(),
std::atomic提供的新操作是指针算术运算。这种基本的操作是由fetch_add()和fetch_sub()成员函数提供。

不要在锁定范围之外,向受保护的数据通过将其作为参数传递给用户所提供的函数的方式,传递指针和引用。一般情况下,编译器无法为std::atomic生成无锁代码,所以它必须对所有的操作使用一个内部锁

有锁和无锁的并发设计

todo

七、C++模板问题 模板元编程 POD 类型萃取

template

  • 类的模板可以偏特化,函数的不可以,因为函数偏特化的功能可以通过重载来实现
  • 类的特化问题,偏特化等
  • 函数的模板
  • 类的模板问题

ref chromium //third_party/blink/renderer/platform/heap/heap.h

// Constructs an instance of T, which is a garbage collected type. This special
// version takes size which enables constructing inline objects.
template 
T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) {
  T* object = MakeGarbageCollectedTrait::Call(additional_bytes,
                                                 std::forward(args)...);
  PostConstructionHookTrait::Call(object);
  return object;
}

多参数问题,函数模板,完美转发,特化,类型萃取,MakeGarbageCollectedTrait ,GC类型萃取

template 
struct MakeGarbageCollectedTrait {
  template 
  static T* Call(Args&&... args) {
    static_assert(WTF::IsGarbageCollectedType::value,
                  "T needs to be a garbage collected object");
    static_assert(
        std::is_trivially_destructible::value ||
            std::has_virtual_destructor::value || std::is_final::value ||
            internal::IsGarbageCollectedContainer::value ||
            internal::HasFinalizeGarbageCollectedObject::value,
        "Finalized GarbageCollected class should either have a virtual "
        "destructor or be marked as final");
    static_assert(!IsGarbageCollectedMixin::value ||
                      sizeof(T) <= kLargeObjectSizeThreshold,
                  "GarbageCollectedMixin may not be a large object");
    void* memory = T::template AllocateObject(sizeof(T));
    HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
    // Placement new as regular operator new() is deleted.
    T* object = ::new (memory) T(std::forward(args)...);
    header->MarkFullyConstructed();
    return object;
  }

  template 
  static T* Call(AdditionalBytes additional_bytes, Args&&... args) {
    static_assert(WTF::IsGarbageCollectedType::value,
                  "T needs to be a garbage collected object");
    static_assert(
        std::is_trivially_destructible::value ||
            std::has_virtual_destructor::value || std::is_final::value ||
            internal::IsGarbageCollectedContainer::value ||
            internal::HasFinalizeGarbageCollectedObject::value,
        "Finalized GarbageCollected class should either have a virtual "
        "destructor or be marked as final.");
    const size_t size = sizeof(T) + additional_bytes.value;
    if (IsGarbageCollectedMixin::value) {
      // Ban large mixin so we can use PageFromObject() on them.
      CHECK_GE(kLargeObjectSizeThreshold, size)
          << "GarbageCollectedMixin may not be a large object";
    }
    void* memory = T::template AllocateObject(size);
    HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
    // Placement new as regular operator new() is deleted.
    T* object = ::new (memory) T(std::forward(args)...);
    header->MarkFullyConstructed();
    return object;
  }
};

POD, RTTI问题

STL部分容器、算法的实现

gcc gdb使用等等

gcc 用法简介

  • 预处理
    gcc -E hello.c -o hello.i or 或 gcc -E test.c
  • 生成汇编
    ** gcc -S asmex.cpp -lstdc++ -std=c++11 -o asmex3.s
    ** gcc -s hello.c -o hello.s or ** gcc -s hello.i -o hello.s
  • 生成目标文件
    gcc -c hello.s -o hello.o or ** gcc -S hello.c -o hello.o
  • 链接目标文件
    gcc hello.o -o hello
    直接生成 gcc hello.cpp -lstdc++ -std=c++11 -o hello // 带参数编译 ./hello运行
    gcc hello.c
    多个文件 gcc hello1.c hello2.c -o hello

g++ -std=c++14 -g3 -pthread -o2 le007.cpp -o le07

  • 静态库和动态库的问题 todo

  • 多个文件以及大型程序的组织参见后文

gdb用法简介. lldb用法

  • 启动调试
  • 断点设置
  • 变量查看
  • 单步调试
  • 源码查看

字符问题 对齐问题

todo

跨平台设计问题

跨平台 -- OS
  • ifdef 宏定义
  • impl设计
  • 目录 命名等区分
跨平台 -- 底层芯片的设计区分

这部分大部分都是涉及到高性能的问题需要注意

  • 线程安全设计时 例如volitile atomic等涉及到内存屏障的问题部分芯片支持的情况不一样(大部分主流芯片都比较一致)
  • 涉及到L1(2,3)cache
  • 涉及到neon优化 和GPU计算高度相关的设计需要注意不同芯片支持的情况
  • 需要注意字符宽度,字符对齐 32位 64位(兼容32位)的区别
  • size_t的使用以及由来 数据总线宽度 和地址宽度的问题

七、 编译 链接过程 以及大型程序的组织 server ex

todo

设计模式

设计模式六大原则

总原则:开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。

1、单一职责原则

不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。

2、里氏替换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。

里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

5、迪米特法则(最少知道原则)(Demeter Principle)

就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

6、合成复用原则(Composite Reuse Principle)

原则是尽量首先使用合成/聚合的方式,而不是使用继承。

三大类 23钟设计模式

创建型模式

工厂模式 抽象工厂模式 build模式 单例模式 原型模式

工厂模式 & 抽象工厂模式
  • 定义Product
class Product {
    public:
        Product() {}
};
class ConcreteProduct: public Product {
     public:
            ConcreteProduct() {}
}
  • 定义工厂
class Factory {
    public:
          ////////
        Product* FactoryMethod()  {
            return new Product();
        }
       // or 
             Product* FactoryMethod2(char * productName)  {
            if (strcmp(productName, "xxxxxx")) {
                return new ConcreteProduct();   
            // todo else if
        }
    private:
      Product * product;
}
class ConcreteFactory : public Factory {
   public: 
           Product * FactoryMethod () {
          return new ConcreteProduct();
       }
}
单例模式

danli

class Singleton { 
     public: 
          Singleton()  { 
            cout<<"Singleton default construct"< lock(mu); // 加锁
                if (_instance == NULL)  {
                      _instance = new  Singleton();
                 }
            }
       
                    return _instance;
               }
    private:
      static Singleton * _instance;

     // 考虑线程安全
          static mutex mu;
};
  • 初始化static变量
Singleton *  Singleton::_instance = nullptr;
 mutex Singleton::mu;

call_once方式


class Singleton{
public:
  static Singleton& getInstance(){
    std::call_once(initInstanceFlag, &Singleton::initSingleton);
    // volatile int dummy{};
    return *instance;
  }
private:
  Singleton() = default;
  ~Singleton() = default;
  Singleton(const MySingleton&) = delete;
  Singleton& operator= (const MySingleton&) = delete;
  static Singleton* instance;
  static std::once_flag initInstanceFlag;
  static void initSingleton() {
    instance = new Singleton;
  }
};

Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::initInstanceFlag;
  • 实际调用示例
        
void print() {
    //this_thread::sleep_for(std::chrono::milliseconds(1000));
    Singleton::getInstance()->SingletonPrint();
}



int  main() {
    thread tA(print);
    thread tB(print);
    tA.join();
    tB.join();
    
    return 0;
}
Build模式

class Maze {
    public:
        Maze() { cout<<"Maze construct function<BuildRoom(10);
            builder->BuildDoor(10,11);
        }
    private:
        MazeBuilder * builder;
};

proto模式

class Proto {
    public:
        //virtual Proto() = delete;
        virtual ~Proto() {}
        virtual Proto* clone() = 0;
        virtual void print() = 0;
};

class ConCreteProto : public Proto{
    public:
        ConCreteProto() {};
        
        ConCreteProto(int _val, const string & _valStr) {
            val = _val;
            valStr = _valStr;
        }
        
         virtual ~ConCreteProto( ) {}
         
        virtual Proto* clone() {
            ConCreteProto *p = new ConCreteProto();
            p->val = val;
            p->valStr = valStr;
            return p;
        }
        
        void print() {
            cout<<"val = "<
Proxy模式

class Graphic {
    public: 
        virtual void Draw() = 0;
        virtual void GetExtend() = 0;
};

class Image : public Graphic {
    public: 
        void Draw() {} 
        void GetExtend() {}
        Image * loadImage() { Image * m = new Image(); return m;}
};

class ImageProxy : public Graphic  {
    public:
        void Draw() {
            if(image == nullptr) {
                image = loadImage();
            }
            image->Draw();
        }
        void GetExtend() {
            
        }
    private:
        Image * image;
}
Flyweight享元模式

运用共享技术有效地支持大量细粒度的对象


class Flyweight {
    public:
        virtual void draw() = 0;
};

class ConcreteFlyweight {
    public:
        void draw() {
            cout<<"drawing"< flyweightMap;
};

装饰模式

动态地给一个对象添加一些额外的职责


class Component {
    public: 
        virtual void draw() = 0;
};

class ConcreteComponent : public Component {
    public:
    void draw () {
        cout<< "ConcreteComponent draw "<draw();
        }
        
    protected:
        Component * component;
};

class XDecorate : public Decorate {
    public:
        XDecorate(Component * _component) : Decorate(_component) {}
            // 
        void draw() {
            Decorate::draw();
            addOperation();
        }
        
    private:
        void addOperation() { cout<<"addOperation"<

C++初始化列表的注意事项。

In a non-delegating constructor, initialization proceeds in the following order:

— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.

— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

— Finally, the compound-statement of the constructor body is executed.

组合


class Component {
    public:
        virtual void operation() = 0;
};

class Leaf : public Component {
    public:
        void operation ()  {
            cout<<"Leaf operation"<operation();
            }
        }
        
        void add(Component * _component) {
            children.push_back(_component);
        }
        
        void remove(Component * _component) {
            
        }
        
    private:
        vector children;
};

facade

行为模式

模板模式
class Game {    // 定义基础游戏
    public: 
     explicit Game(uint32_t players): m_no_of_players(players) {}
    void run() {
        start();
        while (!have_winner())
            take_turn();
        cout << "Player " << get_winner() << " wins.\n";
    }
protected:
    virtual void start() = 0;
    virtual bool have_winner() = 0;
    virtual void take_turn() = 0;
    virtual uint32_t get_winner() = 0;
    uint32_t m_current_player{0};
    uint32_t m_no_of_players{0};
};

class Chess : public Game {   // 定义具体游戏规则
    public:
    explicit Chess(): Game {2} {}
protected:
    void start() {
        cout << "Starting chess with " << m_no_of_players << " players\n";
    }
    bool have_winner() { return m_turns == m_max_turns; }
    void take_turn() {
        cout << "Turn " << m_turns << " taken by player " << m_current_player << "\n";
        m_turns++;
        m_current_player = (m_current_player + 1) % m_no_of_players;
    }
    uint32_t get_winner() { return m_current_player; }
    
private:
    uint32_t m_turns{0}, m_max_turns{4};
};
策略模式

策略模式 可以为client提供一系列不同的实现方式


class Compositor {
    public:
        void strategy() = 0;
};

class XCompositor {
    public:
        void strategy() {
            cout<<"XCompositor strategy"
        }
};

class WCompositor {
    public:
        void strategy(int v) {  // depends on v
            cout<<"WCompositor strategy"
        }
};

class Composition {
    public:
        void SetStrategy(int strategyEnum) {
           switch(strategyEnum) {
                compositor = new WCompositor; 
                break;
        }
        void DoStrategy() {
            compositor->strategy();
        }
    private:
        Compositor * compositor;
}
状态模式
  • Classic

class StateContext;

class State {
    public:
        virtual void open(StateContext * context) = 0;
        virtual void send(StateContext * context) = 0;
        virtual void close(StateContext * context) = 0;
    protected:
        void changeState(StateContext * context, State *state);
};


class StateContext {
    public:
        void open() {
            state->open(this);
        }
        void send() {
            state->send(this);
        }
        void close() {
            state->close(this);
        }
        

        friend class State;
        
        void changeState(State * _state) {
            state = _state;
        }
    private:
        State * state;
};

class XState : public State {
    public:
        static State * getInstance() {
            return new XState();
        }
      void open(StateContext * context) {
        cout<<"XState open"<changeState(state);
        }
    
};

todo modern C++ design pattern

观察者模式

class Observer {
    public:
        virtual void update() = 0;
};


class Subject {
    public:
        void doSub() {}
        void notify() {
            for(auto observer:observers) {
                observer->update();
            }
        }
        void attach(Observer * ob) {
            observers.push_back(ob);
        }
    private:
        list  observers;
};


class XObserver : public Observer {
    public:
        void update() {
            cout<<"XObserver update"<
备忘录memento
中介模式
command
visitor
职责链
迭代
interprate

Modern Design Patterns

Type Erasure
CRTP
// CRTP example
  template
  class Base {
    public:
        void show() const {
            static_cast(this)->show();
        }
        
         Base operator++() {
            static_cast< T*>(this)->operator++();
        }
  };
  
  class Derive : public Base {
    public:
        Derive() : val(0) {}
        void show() const {
            cout<<"derive class object val = "<val);
        return *this;
    }
        
    private:
        int val;
  };

example

    Derive d;
    Base *b = &d;
    b->show();
    ++(*b);
    b->show();
    
Expression Templates
Policy Based Design

面向对象的内存布局 , 引用折叠

各类继承方式的内存布局情况
一般继承,virtual继承,菱形继承,等等这些情况的内存布局,以及涉及到static成员的内存布局以及常见使用示例。

malloc free算法,size_t的由来, 系统启动,,,Linux和windows应用程序的构造区别等等

OS有关的问题 CPU访问内存, MMU内存管理单元 ,段页式内存管理

linux常用命令

编译原理的有关问题

你可能感兴趣的:(C++(98/11)问题 (2))