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

C++通过引用触发析构函数问题求助(附测试代码)

Hey there! Let's dig into this destructor issue you're hitting with references in C++. Since your code snippet cuts off at the constructor definition, I'll fill in the logical gaps based on common scenarios with reference-related destructor surprises, and walk through the most likely causes and fixes.

Troubleshooting Unexpected Destructor Triggers with C++ References

First, let's restate your partial code for clarity:

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include <type_traits>
#include <sstream>

struct Procedure {
    Procedure(HANDLE) {
        std::cout << "ctor w/connection: " << this << std::endl;
    }
    ~Procedure() {
        std::cout << "dtor: " << this << std::endl;
    }
    // Incomplete: likely copy/move constructor or assignment operator
    Procedure(Pr... 
};

Common Scenarios Causing Unexpected Destructor Calls

1. Non-const References Bound to Temporary Objects

If you're binding a non-const reference to a temporary Procedure object, the temporary gets destroyed immediately after the statement finishes—even if the reference is still in scope. This leads to a dangling reference and an unexpected destructor call.

Example of bad code:

void risky_func() {
    // Temporary object is created here, then destroyed right after this line
    Procedure& bad_ref = Procedure(GetCurrentProcess());
    // bad_ref now points to a destroyed object; any use is undefined behavior
}

Fix: Use a const reference (which extends the temporary's lifecycle to match the reference's) or create a named object instead:

void safe_func() {
    Procedure proc(GetCurrentProcess()); // Named object with proper lifecycle
    Procedure& ref = proc; // Reference binds to a valid, long-lived object
    // ref is safe to use here; proc destructs when the function exits
}

2. References Pointing to Container Elements That Get Destroyed

If your Procedure objects live in a container like std::vector, operations like push_back, reserve, or erase can destroy existing elements (e.g., during reallocation). Any references to those elements become dangling, and you'll see unexpected destructor calls when the elements are destroyed.

Example of the issue:

std::vector<Procedure> procs;
procs.emplace_back(GetCurrentProcess());
Procedure& elem_ref = procs[0]; // Reference to the first element

procs.reserve(10); // Vector reallocates, destroying the original element
// elem_ref now dangles; the destructor for the original object was called during reallocation

Fix: Reserve space upfront if you know the container size, or use pointers/smart pointers instead of references to avoid dangling when the container changes.

3. Missing or Incorrect Copy/Move Semantics

If you haven't explicitly defined copy/move constructors or assignment operators for Procedure, the compiler generates default versions. These defaults perform shallow copies, which can lead to double-destruction (e.g., if your class holds a HANDLE that gets copied instead of transferred).

Example of problematic default behavior:

// Compiler-generated copy constructor copies the HANDLE
Procedure proc1(GetCurrentProcess());
Procedure proc2 = proc1; // Shallow copy: both proc1 and proc2 hold the same HANDLE

// When proc1 destructs, it closes the HANDLE; proc2's destructor will operate on an invalid HANDLE

Fix: Explicitly delete copy operations (if your class shouldn't be copied) or implement proper move semantics to transfer ownership of resources:

struct Procedure {
    Procedure(HANDLE h) : handle(h) {
        std::cout << "ctor w/connection: " << this << std::endl;
    }
    ~Procedure() {
        if (handle != INVALID_HANDLE_VALUE) {
            CloseHandle(handle);
        }
        std::cout << "dtor: " << this << std::endl;
    }

    // Disable copying
    Procedure(const Procedure&) = delete;
    Procedure& operator=(const Procedure&) = delete;

    // Implement move semantics
    Procedure(Procedure&& other) noexcept : handle(other.handle) {
        other.handle = INVALID_HANDLE_VALUE;
        std::cout << "move ctor: " << this << std::endl;
    }
    Procedure& operator=(Procedure&& other) noexcept {
        if (this != &other) {
            if (handle != INVALID_HANDLE_VALUE) {
                CloseHandle(handle);
            }
            handle = other.handle;
            other.handle = INVALID_HANDLE_VALUE;
            std::cout << "move assign: " << this << std::endl;
        }
        return *this;
    }

private:
    HANDLE handle = INVALID_HANDLE_VALUE;
};

Next Steps to Debug

  1. Complete your class definition: Add all constructors, assignment operators, and member variables so you can track resource ownership.
  2. Log all constructor calls: Add output to copy/move constructors to see exactly when objects are created and copied/moved.
  3. Audit reference usage: Check every place you use a reference to a Procedure—ensure it's not binding to a temporary or a container element that might be destroyed.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:34:07