C++模板类Address无法正确返回指向数据的问题求助
问题:unique_ptr实例化模板类后无法正确获取指针指向的数据
我定义了如下C++模板类Address,通过std::unique_ptr实例化后,输出结果中Item字段为空,使用char或int类型均存在该问题,请问如何正确获取指针指向的数据?
原代码
#include <iostream> #include <memory> template <typename T> class Address { private: T* ptr; size_t size; public: Address(T item) : ptr(&item), size(sizeof(item)) {} T getItem() const { return *ptr; } long getAddress() const { return (long int ) ptr; } long getSize() const { return size; } }; template <typename T> std::ostream& operator<<(std::ostream& out, const Address<T> item) { out << "\nItem: " << item.getItem() << "\n"; out << "Address : " << item.getAddress() << "\n"; out << "Size : " << item.getSize() << "\n"; return out; } int main() { std::unique_ptr<Address<char>> ptr_addressObj(new Address('P')); std::cout<< *ptr_addressObj << "\n"; }
运行结果
Item: Address : 140720983114340 Size : 1
问题根源
构造函数Address(T item)中的参数item是临时拷贝变量,构造函数执行完毕后该临时变量会被销毁,此时类成员ptr指向的是一块已释放的内存,后续访问*ptr属于未定义行为,所以输出的Item为空或乱值——这和是否使用unique_ptr无关,本质是悬空指针问题。
修复方案
方案一:类自行管理内存(适合必须用指针的场景)
修改构造函数为成员指针分配独立内存并拷贝值,同时添加析构函数释放内存,避免内存泄漏:
template <typename T> class Address { private: T* ptr; size_t size; public: // 用const引用接收参数,减少不必要拷贝 Address(const T& item) : ptr(new T(item)), size(sizeof(T)) {} // 析构函数释放内存 ~Address() { delete ptr; } // 禁用拷贝构造和赋值,避免double free问题 Address(const Address&) = delete; Address& operator=(const Address&) = delete; T getItem() const { return *ptr; } long getAddress() const { return (long int ) ptr; } long getSize() const { return size; } };
方案二:直接存储值(更简单,无指针风险)
既然类仅需保存单个元素,没必要使用指针,直接存储值即可:
#include <iostream> #include <memory> template <typename T> class Address { private: T item; size_t size; public: Address(T item) : item(item), size(sizeof(item)) {} T getItem() const { return item; } // 获取存储值的内存地址 long getAddress() const { return (long int ) &item; } long getSize() const { return size; } }; // 用const引用接收参数,避免不必要拷贝 template <typename T> std::ostream& operator<<(std::ostream& out, const Address<T>& item) { out << "\nItem: " << item.getItem() << "\n"; out << "Address : " << item.getAddress() << "\n"; out << "Size : " << item.getSize() << "\n"; return out; } int main() { std::unique_ptr<Address<char>> ptr_addressObj(new Address('P')); std::cout << *ptr_addressObj << "\n"; }
修复后运行结果
Item: P Address : 140720983114340 Size : 1
内容的提问来源于stack exchange,提问作者Chani
相关产品推荐
相关产品推荐

