You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数作用域末尾执行代码的简便方法及测试全局变量恢复问题咨询

Hey there! Let's break down your two C++ questions one by one—both are about reliable scope-based execution/cleanup, which is super critical especially in testing scenarios.

1. 简便地在函数作用域末尾执行代码

The gold standard for this in C++ is RAII (Resource Acquisition Is Initialization). The core idea is to tie the code you want to run at scope end to an object's destructor, since destructors are guaranteed to run no matter how the scope exits (normal return, early return, or exception). Here are two practical approaches:

Option 1: Custom RAII Scope Guard (works with all C++ versions)

You can roll your own tiny struct to wrap any cleanup/end-of-scope logic:

#include <functional>

struct ScopeGuard {
    std::function<void()> cleanupFunc;

    explicit ScopeGuard(std::function<void()> func) 
        : cleanupFunc(std::move(func)) {}

    // Destructor runs automatically when the guard goes out of scope
    ~ScopeGuard() {
        cleanupFunc();
    }

    // Prevent copying to avoid duplicate execution
    ScopeGuard(const ScopeGuard&) = delete;
    ScopeGuard& operator=(const ScopeGuard&) = delete;
};

Usage example:

void processData() {
    // Initialize resources or setup here
    ScopeGuard guard([](){
        // This code runs at the end of the scope, guaranteed
        std::cout << "Cleaning up resources..." << std::endl;
        // e.g., close files, release locks, reset state
    });

    // Your main logic here
    if (someErrorCondition) {
        return; // Guard's destructor still runs!
    }

    throw std::runtime_error("Unexpected issue"); // Destructor runs too!
}

Option 2: C++20 std::scope_exit (native standard library support)

If you're using C++20 or later, skip the custom struct and use the standard library's built-in solution:

#include <scope> // Required header

void processData() {
    auto guard = std::scope_exit([](){
        std::cout << "Executed at scope end!" << std::endl;
    });

    // Same behavior as the custom guard—works with all exit paths
}

2. Automatically Restore Global Variables in Tests (Fix Early Exit/Exception Issues)

Your current manual restore approach fails because if the test exits early (via return or exception), the final setCsrfToken call never runs. RAII is again the perfect fix here—we'll wrap the save/restore logic into a struct that handles it automatically.

Solution: RAII Wrapper for Global State

Let's create a specialized guard for your CSRF token scenario first:

struct CsrfTokenRestorer {
    std::string originalToken;

    CsrfTokenRestorer() {
        // Save the current token when the guard is created
        originalToken = Http::getCsrfToken();
    }

    ~CsrfTokenRestorer() {
        // Restore the original token when the guard goes out of scope
        Http::setCsrfToken(originalToken);
    }

    // Prevent copying to avoid conflicting restores
    CsrfTokenRestorer(const CsrfTokenRestorer&) = delete;
    CsrfTokenRestorer& operator=(const CsrfTokenRestorer&) = delete;
};

Now update your test case to use this guard:

BOOST_AUTO_TEST_CASE(HttpClientCsrf) { 
    CsrfTokenRestorer tokenGuard; // Automatically saves the current CSRF token

    // Modify the token for testing
    Http::setCsrfToken("test-csrf-123");

    // Your test logic here
    if (someTestFailure) {
        BOOST_TEST_FAIL("Invalid CSRF response"); // Exception thrown—restore still happens
        return; // Early return—restore still happens
    }

    // No need for manual restore code anymore!
}

Generic Version (Works for Any Global Variable)

If you need this for multiple global variables, a template-based guard is even more flexible:

template<typename T>
struct GlobalStateRestorer {
    T& globalVar;
    T originalValue;

    explicit GlobalStateRestorer(T& var) 
        : globalVar(var), originalValue(var) {}

    ~GlobalStateRestorer() {
        globalVar = originalValue;
    }

    GlobalStateRestorer(const GlobalStateRestorer&) = delete;
    GlobalStateRestorer& operator=(const GlobalStateRestorer&) = delete;
};

Usage for your CSRF token (assuming Http::csrfToken is a directly accessible global variable):

BOOST_AUTO_TEST_CASE(HttpClientCsrf) { 
    GlobalStateRestorer<std::string> tokenGuard(Http::csrfToken);

    Http::csrfToken = "test-csrf-123";

    // Test logic...
    // Automatic restore on scope exit
}

Why This Works

C++ guarantees that an object's destructor will execute when it goes out of scope, regardless of how the scope is exited. This eliminates the risk of forgetting to restore state or missing the restore step due to early exits/exceptions.

内容的提问来源于stack exchange,提问作者Pavel P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:14:24