std::optional<T>的值地址是否稳定?多次重置赋值后地址是否恒定?
Great question! Let's break down whether the address of the value inside a std::optional<T> stays consistent through resets and assignments.
Short Answer
If your std::optional<T> object itself stays in the same memory location (i.e., it's not moved, copied to a new spot, or reallocated), the address of the contained T will almost always stay the same in mainstream C++ implementations. However, the C++ standard doesn't explicitly guarantee this stability—though it's a safe assumption for practical use.
Detailed Explanation
Let's unpack how std::optional works and why address stability holds in practice:
- Internal Storage Design: All standard-compliant
std::optionalimplementations store theTobject directly within theoptional's own memory footprint—no dynamic allocation is involved. The object's size is at leastsizeof(T) + sizeof(bool)(plus alignment padding) to fit both the value and a "has value" flag. This means the space forTis fixed as part of theoptionalobject itself. - Reset Behavior: Calling
reset()only destroys the containedTobject; it doesn't free or reallocate the memory space reserved forT. That space remains part of theoptionalobject. - Reassigning/Emplacing: When you later assign a value to an empty
optional(e.g.,opt = 42) or useemplace()to construct a newT, the new object is built in the exact same reserved memory space. Hence, its address matches the address of any previousTstored in thatoptional.
Example to Demonstrate Consistent Addresses
Here's a quick code snippet that shows addresses stay the same across resets and assignments:
#include <optional> #include <iostream> int main() { std::optional<int> opt; // First assignment opt = 42; std::cout << "Address after first assignment: " << &*opt << '\n'; // Reset and emplace a new value opt.reset(); opt.emplace(100); std::cout << "Address after emplace: " << &*opt << '\n'; // Assign another value to a non-empty optional opt = 200; std::cout << "Address after second assignment: " << &*opt << '\n'; return 0; }
Run this with GCC, Clang, or MSVC, and you'll see the same address printed every time.
The Caveat: Standard Doesn't Explicitly Mandate It
While all major implementations follow this pattern, the C++ standard only requires std::optional to provide storage for T and necessary accessors. It doesn't explicitly force the storage location to stay fixed across resets and assignments. That said, there's no practical reason for an implementation to change the storage location—doing so would add unnecessary complexity and go against std::optional's design intent of avoiding dynamic allocation.
When Addresses Will Change
If you move or copy the std::optional object itself (e.g., std::optional<int> new_opt = std::move(old_opt)), the contained T will be in a new memory location (since new_opt is a separate object). But your question focuses on operations on the same optional object, so this case doesn't apply here.
内容的提问来源于stack exchange,提问作者Rumburak

