使用 std::vector<> 和 std::shared_ptr<> 应该会导致错误

Using std::vector<> and std::shared_ptr<> should cause error

本文关键字:gt lt std 错误 vector 使用 shared ptr      更新时间:2023-10-16

下面是我所做的代码:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;
int main()
{
  vector<int> ar = {1};
  shared_ptr<int> sp(&ar[0]);
  cout<<*sp<<endl; // ---- [1]
  ar[0] = 10;
  cout<<*sp<<endl; // ---- [2]
  ar.clear();
  cout<<*sp<<endl; // ---- [3]

  return 0;
}

输出将是:

1
10
10

而不是cout at [3],我认为在运行时应该有任何错误,因为要访问的对象已经被删除了。如何在[3]中打印10 ?或者我应该使用任何g++标志,我只是使用g++ -std=c++14 a1.cpp && ./a.out

编辑:在Coliru上运行时,我发现clang++正在给予

`*** glibc detected *** ./a.out: double free or corruption (fasttop):     0x0000000002138010 ***`

g++不是Coliru。

当你试图访问vector的当前边界外时,你基本上绕过了任何可能导致运行时错误的因素。

如果你想检查边界,你可以考虑这样做:

std::vector<int> ar { 1 };
std::cout << ar.at(0); // no problem
ar.clear();
std::cout << ar.at(0); // guaranteed to throw an exception

shared_ptr表示对象的共享所有权,因此只有当对象没有剩余所有权时才会删除它。相比之下,std::vector假定单独拥有它所包含的所有对象,因此试图用shared_ptr引用其中一个对象只会导致问题。

另一方面,在gcc中,这在没有(可见的)问题迹象的情况下成功退出,从技术上讲,这并不能算作编译器中的错误。在作用域的最后,shared_ptrstd::vector都将尝试释放shared_ptr所引用的int——但是没有要求这样做会导致错误消息(正式地说,这是一个实现质量问题,尽管我当然同意显示消息总比不显示好)。

您的代码中有几处错误。最明显的一个是,您正在创建一个shared_ptr来管理一个已经由vector管理的对象,并且很可能在main的末尾得到双重删除。

另一个问题是,你有一个指向对象的指针,并在对象被删除后使用它,因为std::vector<int>::clear不会释放内存,你正在击中仍然由向量管理的内存,这就是为什么它不会爆炸,但对象不再存在了,你不应该访问它。如果不是int而是std::string,程序可能会崩溃(也可能没有崩溃,这是未定义行为的本质)

这是一个未定义行为。它可以打印,也可以不打印。

std::vector::clear()删除了对象,不保证重新分配。因此,系统可能不会重用该内存,因此如果访问相同的内存位置,可能会得到旧值。

有一个有趣的观察,如果在std::vector::clear()操作之后检查std::shared_ptr::use_cout(),可以看到答案1。

  vector<int> ar = {1};
  shared_ptr<int> sp(&ar[0]);
  cout<<*sp<<"n"; // ---- [1]
  ar[0] = 10;
  cout<<*sp<<"n"; // ---- [2]
  ar.clear();
  cout<< sp.use_count()<<"n";
  cout<<*sp<<endl; // ---- [3]

输出
1
10
1
10