偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

模仿 gTest 從零實(shí)現(xiàn)一個(gè)測(cè)試框架:使用現(xiàn)代 C++ 改造

開(kāi)發(fā) 測(cè)試
本文將介紹如何使用現(xiàn)代 C++ 特性?xún)?yōu)化代碼,這些改進(jìn)使代碼更現(xiàn)代化,性能更好,同時(shí)保持了原有的功能完整性。

本文將介紹如何使用現(xiàn)代 C++ 特性?xún)?yōu)化代碼,主要包括以下內(nèi)容。下面,讓我們開(kāi)始代碼優(yōu)化之旅!

1. 單例模式的魔法改造

讓我們先看看單例模式的優(yōu)化:

// ?? 使用 inline 關(guān)鍵字讓編譯器更聰明地內(nèi)聯(lián)展開(kāi)
static inline ETest& GetInstance() {
    // ?? static 保證線(xiàn)程安全的懶漢式初始化
    static ETest instance;  
    return instance;        // ?? 返回唯一實(shí)例
}

為什么要這樣改進(jìn)呢? 

  • inline 建議編譯器將函數(shù)內(nèi)聯(lián)展開(kāi),減少函數(shù)調(diào)用開(kāi)銷(xiāo) 
  • static 局部變量保證了線(xiàn)程安全的初始化
  • 返回引用避免了不必要的拷貝

為什么要建議使用 inline? 

  • 減少函數(shù)調(diào)用開(kāi)銷(xiāo)
  • 避免了函數(shù)調(diào)用時(shí)的棧幀創(chuàng)建和銷(xiāo)毀
  • 省去了參數(shù)傳遞和返回值復(fù)制的開(kāi)銷(xiāo)

編譯器優(yōu)化:

  • 讓編譯器有機(jī)會(huì)進(jìn)行更多的上下文相關(guān)優(yōu)化
  • 可以直接在調(diào)用處展開(kāi)代碼,提升執(zhí)行效率

特別適合單例模式:

  • GetInstance() 經(jīng)常被調(diào)用
  • 函數(shù)體積小,非常適合內(nèi)聯(lián)
  • 可以和編譯器的其他優(yōu)化更好地配合

注意事項(xiàng)

  • inline 只是對(duì)編譯器的建議,不是強(qiáng)制命令
  • 現(xiàn)代編譯器已經(jīng)很智能,會(huì)自動(dòng)決定是否內(nèi)聯(lián)
  • 但在關(guān)鍵路徑上顯式標(biāo)記 inline 仍然是好習(xí)慣

2. 現(xiàn)代化的函數(shù)處理方式

來(lái)看看如何讓函數(shù)調(diào)用更靈活:

// ?? 使用 std::function 支持各種可調(diào)用對(duì)象
using TestFunction = std::function<void()>;

// ?? 支持移動(dòng)語(yǔ)義的測(cè)試用例添加
void AddTest(std::string name, TestFunction test_func) {
    // ?? 使用 emplace_back 直接構(gòu)造,避免拷貝
    tests_.emplace_back(std::move(name), std::move(test_func));
}

這樣改進(jìn)的好處是:

  • 可以接受 lambda 表達(dá)式啦!
  • 支持任何可調(diào)用對(duì)象,更加靈活
  • 使用移動(dòng)語(yǔ)義提升性能

為什么使用值傳遞而不是引用? 

你可能會(huì)問(wèn):為什么 name 參數(shù)要從之前的引用傳遞 const std::string& 改為值傳遞?這其實(shí)是現(xiàn)代 C++ 的一個(gè)最佳實(shí)踐!

// ?? 兩種方式的對(duì)比
void AddTest(std::string name, ...);              // ? 值傳遞方式
void AddTest(const std::string& name, ...);       // ? 引用方式

值傳遞的優(yōu)勢(shì):

  • 臨時(shí)對(duì)象情況
// 場(chǎng)景1: 傳入字符串字面量
AddTest("test_name", ...);  // 值傳遞:0次拷貝(直接移動(dòng))
                            // 引用傳遞:1次拷貝(在emplace_back時(shí))

// 值傳遞的過(guò)程:
// 1. "test_name" -> 創(chuàng)建臨時(shí) std::string
// 2. 通過(guò)移動(dòng)構(gòu)造傳入函數(shù)
// 3. 通過(guò)移動(dòng)構(gòu)造存入 vector
// 總計(jì): 1次構(gòu)造, 2次移動(dòng)

// 引用傳遞的過(guò)程:
// 1. "test_name" -> 創(chuàng)建臨時(shí) std::string (作為引用參數(shù))
// 2. 在 vector.emplace_back 時(shí)復(fù)制構(gòu)造
// 總計(jì): 1次構(gòu)造, 1次拷貝
  • 具名變量情況
std::string name = "test";
AddTest(name, ...);         // 值傳遞:1次拷貝
                            // 引用傳遞:1次拷貝(在emplace_back時(shí))

// 值傳遞的過(guò)程:
// 1. name 被拷貝構(gòu)造到函數(shù)參數(shù)
// 2. 函數(shù)參數(shù)被移動(dòng)構(gòu)造到 vector
// 總計(jì): 1次拷貝, 1次移動(dòng)

// 引用傳遞的過(guò)程:
// 1. name 作為引用傳入(無(wú)開(kāi)銷(xiāo))
// 2. 在 vector.emplace_back 時(shí)拷貝構(gòu)造
// 總計(jì): 1次拷貝
  • 移動(dòng)語(yǔ)義情況
std::string name = "test";
AddTest(std::move(name), ...);  

// 值傳遞的過(guò)程:
// 1. name 被移動(dòng)構(gòu)造到函數(shù)參數(shù)
// 2. 函數(shù)參數(shù)被移動(dòng)構(gòu)造到 vector
// 總計(jì): 2次移動(dòng)

// 引用傳遞的過(guò)程:
// 1. 移動(dòng)后的 name 作為引用傳入
// 2. 在 vector.emplace_back 時(shí)移動(dòng)構(gòu)造
// 總計(jì): 1次移動(dòng)

性能分析總結(jié):

  • 臨時(shí)對(duì)象:值傳遞略勝(避免了一次拷貝)
  • 具名變量:基本持平(都需要一次拷貝)
  • 移動(dòng)語(yǔ)義:引用傳遞略勝(少一次移動(dòng))

但考慮到:

(1) 代碼可維護(hù)性

  • 值傳遞明確表明參數(shù)會(huì)被存儲(chǔ)
  • 避免懸垂引用風(fēng)險(xiǎn)
  • 性能表現(xiàn)更加統(tǒng)一和可預(yù)測(cè)

(2) 代碼清晰度

  • 值傳遞的語(yǔ)義更清晰
  • 不需要考慮參數(shù)生命周期
  • 減少 std::move 的使用場(chǎng)景

(3) 編譯器優(yōu)化

  • 現(xiàn)代編譯器對(duì)值傳遞有很好的優(yōu)化
  • 可以利用 RVO/NRVO 優(yōu)化
  • 內(nèi)聯(lián)時(shí)可能消除額外的開(kāi)銷(xiāo)

因此,在這種"參數(shù)最終會(huì)被存儲(chǔ)"的場(chǎng)景下,推薦使用值傳遞。這種"按值傳遞并移動(dòng)"的模式已成為現(xiàn)代 C++ 的最佳實(shí)踐。?

3. 性能小貼士

看看這些貼心的性能優(yōu)化:

// ?? 構(gòu)造函數(shù)中預(yù)分配內(nèi)存
ETest() { 
    tests_.reserve(100);  // ?? 避免頻繁擴(kuò)容
}

// ?? 測(cè)試用例的完美轉(zhuǎn)發(fā)構(gòu)造
TestCase(std::string n, TestFunction f) 
    : name(std::move(n)),    // ?? 移動(dòng)而不是拷貝
      func(std::move(f)) {}  // ?? 同樣移動(dòng)提升性能

這些優(yōu)化的效果:

  • 預(yù)分配內(nèi)存減少重新分配的次數(shù)
  • 移動(dòng)語(yǔ)義避免不必要的拷貝
  • 構(gòu)造函數(shù)初始化列表更高效

4. 更智能的斷言

來(lái)看看更強(qiáng)大的斷言實(shí)現(xiàn):

#define ASSERT_EQ(expected, actual)                    \
  do {                                                 \
    const auto& exp = (expected);    // ?? 避免重復(fù)求值  \
    const auto& act = (actual);      // ?? 使用引用     \
    if (exp != act) {               // ?? 比較結(jié)果      \
      // ... 錯(cuò)誤處理 ...           // ?? 清晰的錯(cuò)誤信息 
    }                                                 \
  } while (0)                       // ??? 安全的宏結(jié)構(gòu)

為什么這樣寫(xiě)更好:

  • do-while(0) 讓宏更安全
  • 引用避免重復(fù)計(jì)算
  • 清晰的錯(cuò)誤信息更容易調(diào)試

每個(gè)小改進(jìn)都在讓代碼變得更好,這就是現(xiàn)代 C++ 的魔力! 

5. 異常安全性與const正確性

// ??? 使用 noexcept 標(biāo)記不會(huì)拋出異常的函數(shù)
void RunAllTests() noexcept {
    TestStats stats;
    // ...
}

// ? 使用 const 成員函數(shù)表明函數(shù)不會(huì)修改對(duì)象狀態(tài)
void PrintTestSummary(const TestStats& stats) const {
    // ...
}

為什么要使用這些特性?

(1) noexcept 的優(yōu)勢(shì)

  • 提供編譯器優(yōu)化機(jī)會(huì)
  • 明確函數(shù)的異常安全性保證
  • 避免異常展開(kāi)帶來(lái)的性能開(kāi)銷(xiāo)
  • 在STL容器操作中可能獲得更好的性能

(2) const 成員函數(shù)的好處

  • 表明函數(shù)不會(huì)修改對(duì)象狀態(tài)
  • 允許在const對(duì)象上調(diào)用
  • 提高代碼可讀性和可維護(hù)性
  • 幫助編譯器進(jìn)行優(yōu)化

6. 字符串視圖優(yōu)化

// 使用 std::string_view 優(yōu)化字符串處理
void LogError(std::string_view message) {
    std::cout << message << std::endl;
}

std::string_view 的優(yōu)勢(shì):

  • 零拷貝字符串操作
  • 可以直接接受字符串字面量
  • 比 const std::string& 更輕量
  • 適用于只讀字符串場(chǎng)景

使用場(chǎng)景:

// 舊方式
void Log(const std::string& msg);  // 可能導(dǎo)致不必要的字符串構(gòu)造

// 新方式
void Log(std::string_view msg);    // 更高效,沒(méi)有額外開(kāi)銷(xiāo)

// 使用示例
Log("直接使用字面量");            // ? 完全沒(méi)有構(gòu)造開(kāi)銷(xiāo)
std::string str = "test";
Log(str);                         // ? 也可以接受 string

這些現(xiàn)代C++特性不僅能提升代碼的性能,還能增加代碼的安全性和可維護(hù)性。在適當(dāng)?shù)膱?chǎng)景下使用這些特性,能讓我們的代碼更加優(yōu)雅和高效。

總結(jié)

主要優(yōu)化點(diǎn)包括:

  • 使用 std::function 替代函數(shù)指針,提供更好的靈活性,支持 lambda 表達(dá)式和其他可調(diào)用對(duì)象
  • 添加 inline 關(guān)鍵字優(yōu)化單例實(shí)現(xiàn)
  • 使用 std::move 和移動(dòng)語(yǔ)義優(yōu)化性能
  • 添加 noexcept 標(biāo)記提供更好的異常安全性保證
  • 使用 const 成員函數(shù)增加代碼的可維護(hù)性
  • 使用 std::string_view 優(yōu)化字符串處理
  • 改進(jìn)斷言宏的實(shí)現(xiàn),使用 do {...} while(0) 結(jié)構(gòu)確保宏的安全性
  • 為 vector 預(yù)留空間,減少重新分配
  • 使用構(gòu)造函數(shù)初始化列表優(yōu)化對(duì)象構(gòu)造
  • 使用 emplace_back 替代 push_back 提高性能

這些改進(jìn)使代碼更現(xiàn)代化,性能更好,同時(shí)保持了原有的功能完整性。

完整代碼

完整代碼如下:

#ifndef ETEST_H
#define ETEST_H

#include <chrono>
#include <functional>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

class ETest {
public: // 公開(kāi)接口 ??
  // 獲取單例實(shí)例 ??
  static inline ETest &GetInstance() {
    static ETest instance;
    return instance;
  }

  // 測(cè)試注冊(cè)器 ??
  using TestFunction = std::function<void()>;
  void AddTest(std::string name, TestFunction test_func) {
    tests_.emplace_back(std::move(name), std::move(test_func));
  }

  // 測(cè)試執(zhí)行器 ??
  void RunAllTests() noexcept {
    TestStats stats;
    std::cout << "\033[1;36m?? Starting tests...\033[0m\n";

    for (const auto &test : tests_) {
      stats.total++;
      auto start = std::chrono::high_resolution_clock::now();

      try {
        std::cout << "?? Running: " << test.name << std::endl;
        test.func();
        stats.passed++;
        std::cout << "\033[1;32m? PASSED\033[0m: " << test.name << std::endl;
      } catch (const std::exception &e) {
        stats.failed++;
        std::cout << "\033[1;31m? FAILED\033[0m: " << test.name << "\n";
        std::cout << "  Error: " << e.what() << std::endl;
      }

      auto end = std::chrono::high_resolution_clock::now();
      stats.totalTime += std::chrono::duration<double>(end - start).count();
    }

    // 打印統(tǒng)計(jì)結(jié)果
    PrintTestSummary(stats);
  }

private: // 內(nèi)部實(shí)現(xiàn) ??
  // 私有構(gòu)造函數(shù) - 防止外部創(chuàng)建實(shí)例 ??
  ETest() { tests_.reserve(100); }

  // 刪除拷貝和賦值功能 - 確保唯一性 ?
  ETest(const ETest &) = delete;
  ETest &operator=(const ETest &) = delete;

  struct TestCase {
    std::string name;  // 測(cè)試名稱(chēng)
    TestFunction func; // 測(cè)試函數(shù)指針 ??

    // 使用構(gòu)造函數(shù)初始化列表
    TestCase(std::string n, TestFunction f)
        : name(std::move(n)), func(std::move(f)) {}
  };

  std::vector<TestCase> tests_; // 存儲(chǔ)所有測(cè)試用例 ??

  // 添加測(cè)試結(jié)果統(tǒng)計(jì)
  struct TestStats {
    int total = 0;
    int passed = 0;
    int failed = 0;
    double totalTime = 0.0;
  };

  void PrintTestSummary(const TestStats &stats) const {
    std::cout << "\n=========================\n";
    std::cout << "?? Test Summary:\n";
    std::cout << "Total: " << stats.total << " tests\n";
    std::cout << "\033[1;32mPassed: " << stats.passed << "\033[0m\n";
    std::cout << "\033[1;31mFailed: " << stats.failed << "\033[0m\n";
    std::cout << "Time: " << std::fixed << std::setprecision(3)
              << stats.totalTime << "s\n";
    std::cout << "=========================\n";
  }
};

// 改進(jìn)斷言宏,使用 constexpr 和 std::string_view
#define ASSERT(condition)                                                      \
  if (!(condition)) {                                                          \
    const auto message = std::string("Assertion failed: ") + #condition;       \
    std::cout << "\033[1;31m" << message << "\033[0m\n"                        \
              << "File: " << std::string_view(__FILE__) << "\n"                \
              << "Line: " << __LINE__ << std::endl;                            \
    throw std::runtime_error(message);                                         \
  }

// 使用模板改進(jìn) ASSERT_EQ
#define ASSERT_EQ(expected, actual)                                            \
  do {                                                                         \
    const auto &exp = (expected);                                              \
    const auto &act = (actual);                                                \
    if (exp != act) {                                                          \
      std::ostringstream oss;                                                  \
      oss << "Expected: " << exp << "\nActual: " << act;                       \
      const auto message = oss.str();                                          \
      std::cout << "\033[1;31mAssertion failed\033[0m\n"                       \
                << message << "\nFile: " << std::string_view(__FILE__)         \
                << "\nLine: " << __LINE__ << std::endl;                        \
      throw std::runtime_error(message);                                       \
    }                                                                          \
  } while (0)

#define TEST(name)                                                             \
  void test_##name();                                                          \
  struct Register##name {                                                      \
    Register##name() { ETest::GetInstance().AddTest(#name, test_##name); }     \
  } register##name##Instance;                                                  \
  void test_##name()

#endif

責(zé)任編輯:趙寧寧 來(lái)源: everystep
相關(guān)推薦

2024-09-25 08:28:45

2020-09-24 11:46:03

Promise

2016-09-14 17:48:44

2019-04-24 15:06:37

Http服務(wù)器協(xié)議

2021-06-30 07:19:36

網(wǎng)絡(luò)安全

2021-08-04 05:49:40

數(shù)據(jù)庫(kù)數(shù)時(shí)序數(shù)據(jù)庫(kù)技術(shù)

2021-09-02 10:01:58

Spring 容器AOP

2011-08-22 13:57:55

gtest

2021-10-27 11:29:32

框架Web開(kāi)發(fā)

2010-02-06 09:46:46

C++單向鏈表

2020-08-07 10:40:56

Node.jsexpress前端

2014-09-25 09:51:29

Android App個(gè)人博客

2011-09-16 10:00:56

C++

2025-05-13 10:17:40

C++現(xiàn)代版AI

2010-02-06 13:42:36

C++單件模式

2022-06-20 09:01:56

Plasmo開(kāi)源

2021-06-08 07:32:01

框架Mock測(cè)試

2021-05-28 18:12:51

C++類(lèi)設(shè)計(jì)

2016-10-20 16:07:11

C++Modern C++異步

2020-08-17 08:20:16

iOSAOP框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)