问题描述
在下面的例子中使用指针让我感到困惑,所以我可能误解了一些东西。我会尽量展示我的理解方式和一些伪简单的例子。
创建名称为 std::unique_ptr
的 my_int
变量确保它不能被复制,并且它的 int
对象只有一个所有者。然后我创建一个向量来存储指针并将其放入而不用 std::emplace_back()
复制。
现在我想检查向量 integers[0]
的元素在内存中是否与原始元素 my_int
具有相同的地址。我认为应该是因为无法复制此元素。
示例代码:
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(my_int.get());
std::cout<< "Value of my_int: " << *my_int << std::endl;
std::cout << "Address of my_int: " << my_int.get() << std::endl;
std::cout << "Also address of my_int: " << &my_int << std::endl;
std::cout << "Also address of my_int: " << &integers[0]<< std::endl;
std::cout << "Also address of my_int: " << integers[0].get()<< std::endl;
测试结果:
Value of my_int: 1
Address of my_int: 0x260fc40
Also address of my_int: 0x65fb58
Also address of my_int: 0x260fe20
Also address of my_int: 0x260fc40
我也尝试使用 std::move()
将对象放到向量中,但效果是一样的,地址不同,但我不明白为什么。
我的第一个困惑是 &my_int
和 my_int.get()
不一样,第二个困惑是 integers[0].get()
也不同于 &integers[0]
。
解决方法
表达式 my_int.get()
返回一个指向所包含整数的指针,其类型为 int*
。
表达式 &my_int
返回一个指向 my_int
对象本身的指针,其类型为 std::unique_ptr<int>*
。
而 integers[0]
是与 my_int
截然不同的对象。它们恰好包含相同的指针。这对于唯一指针来说是不利的:它们一起会尝试释放相同的内存两次。您必须使用std::move
auto my_int = std::make_unique<int>(1);
std::vector<std::unique_ptr<int>> integers;
integers.emplace_back(std::move(my_int)); // push_back also works
这样 my_int
将被设置为包含 nullptr
,并且只有 integers[0]
将包含指向已分配内存的指针。
要更好地理解 my_int
(或一般的指针),您可以这样想:
+--------+ +---+ | my_int | --> | 1 | +--------+ +---+ ^ ^ | | &my_int my_int.get()
integers[0].get()
和 &integers[0]
是一样的。
创建名为 my_int 的 std::unique_ptr 变量确保它不能被复制并且它的 int 对象只有一个所有者。
只有std::unique_ptr
无法复制。但是唯一指针不能保证您不会复制它拥有的裸指针。复制唯一指针拥有的裸指针正是您所做的,这会导致同一资源的两个“唯一”所有者。当第二个唯一指针被销毁时,这将导致未定义的行为。
当您调用 std::unique_ptr::get
时,唯一指针不会将其所有权释放给您。您永远不应该将不属于您的指针传递给智能指针的构造函数。
要解决此问题,您可以通过移动将所有权从一个智能指针转移到另一个智能指针:
integers.emplace_back(std::move(my_int));
地址不同,但我不明白为什么。
唯一指针变量是一个对象,向量的元素是另一个对象。由于它们是单独的对象,因此它们具有单独的地址。即使它们碰巧是指向同一个对象的指针——整数,它又是另一个对象。这三个对象对应于您在输出中看到的三个不同地址。