cpp使用对象实现在作用域开始和结束执行代码的例子

⌚Time: 2023-08-16 22:55:32

👨‍💻Author: Jack Ge

1. std::lock_guard

在c++11中的线程锁std::mutex

用于在代码的关键部分需要独占访问时发出信号,防止具有相同保护的其他线程同时执行并访问相同的内存位置。

在线程互斥代码块之前加锁


mtx.lock();

代码块结束后解锁


mtx.unlock();

例子


// mutex example

#include <iostream>       // std::cout

#include <thread>         // std::thread

#include <mutex>          // std::mutex



std::mutex mtx;           // mutex for critical section



void print_block (int n, char c) {

  // critical section (exclusive access to std::cout signaled by locking mtx):

  mtx.lock();

  for (int i=0; i<n; ++i) { std::cout << c; }

  std::cout << '\n';

  mtx.unlock();

}



int main ()

{

  std::thread th1 (print_block,50,'*');

  std::thread th2 (print_block,50,'$');



  th1.join();

  th2.join();



  return 0;

}

使用std::lock_guard,它在构造时,互斥对象被调用线程锁定,在销毁时,互斥被解锁。

在它的构造函数中,调用互斥锁的lock函数,在他的析构函数中,调用互斥锁unlock函数

例子


// lock_guard example

#include <iostream>       // std::cout

#include <thread>         // std::thread

#include <mutex>          // std::mutex, std::lock_guard

#include <stdexcept>      // std::logic_error



std::mutex mtx;



void print_even (int x) {

  if (x%2==0) std::cout << x << " is even\n";

  else throw (std::logic_error("not even"));

}



void print_thread_id (int id) {

  try {

    // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:

    std::lock_guard<std::mutex> lck (mtx);

    print_even(id);

  }

  catch (std::logic_error&) {

    std::cout << "[exception caught]\n";

  }

}



int main ()

{

  std::thread threads[10];

  // spawn 10 threads:

  for (int i=0; i<10; ++i)

    threads[i] = std::thread(print_thread_id,i+1);



  for (auto& th : threads) th.join();



  return 0;

}

2. MFC类CPaintDC

在WIN32中响应窗体WM_PAINT消息:


LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

    switch (uMsg)

    {

    

    case WM_PAINT:

        {

            PAINTSTRUCT ps;

            HDC hdc = BeginPaint(hwnd, &ps);



            // All painting occurs here, between BeginPaint and EndPaint.

            FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

            EndPaint(hwnd, &ps);

        }

    ...

    }



    return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

其中BeginPaint 函数准备用于绘制的指定窗口,并使用有关绘图的信息填充 PAINTSTRUCT 结构。应用程序不应调用 BeginPaint ,除非响应 WM_PAINT 消息。 对 BeginPaint 的每个调用都必须具有对 EndPaint 函数的相应调用。

EndPaint 函数标记指定窗口中绘制的结尾。 每次调用 BeginPaint 函数时都需要此函数,但仅在绘制完成后才需要此函数。

MFC的OnPaint中CPaintDC dc(this)

CPaintDC


class CPaintDC : public CDC

CPaintDC::CPaintDC 构造连接到指定的 CWnd 的 CPaintDC。

CPaintDC::m_ps 包含用于绘制工作区的 PAINTSTRUCT。

CPaintDC::m_hWnd 附加此 CPaintDC 对象的 HWND。

在构造时执行 CWnd::BeginPaint,在销毁时执行 CWnd::EndPaint。

传递给 CWnd::BeginPaint 并由其填充的是 PAINTSTRUCT。

使用:


void CaaaaaDlg::OnPaint()

{

    CPaintDC dc(this);

    dc.MoveTo(0, 0);

    dc.LineTo(200, 200);

}

3. 在堆栈中对象的区别

在堆中分配的对象,生命周期由程序员控制,需要手动释放内存,并且容易造成内存泄漏。

在栈中的对象,效率很高,但是分配的内存量有限,并且在作用域结束后就会销毁。在对象的析构函数中实现代码,实现在作用域结束执行的操作。