【问题标题】:why a 2-dimensional vector of auto_ptr in C++ does not work?为什么 C++ 中 auto_ptr 的二维向量不起作用?
【发布时间】:2023-03-22 10:36:02
【问题描述】:

我正在研究一个二维向量(向量的向量)以在 C++ 中携带一些指针。

std::vector< std::vector<object*> > data;

这里的对象是一个类,每个数据条目都带有一个指向对象实例的指针。我让它在 C++ 中工作,但是当我将它应用到其他代码时,内存管理使它很难维护。我做了一些研究,有人建议改用智能指针。我尝试以下代码

  #include <vector>
  #include <memory>
  using namespace std;
  
  int main(void) {
    vector< int > source = {1,2,3,4,5};
    vector< auto_ptr<int> > co;
    vector< vector< auto_ptr<int> > > all;

    co.push_back( auto_ptr<int>(&source[0]) );
    co.push_back( auto_ptr<int>(&source[2]) );
    co.push_back( auto_ptr<int>(&source[4]) ); // it works well up to here

    all.push_back(co); // but it crashs here
    return 0;
  }

其中一条错误消息是

C:/msys64/mingw64/include/c++/9.2.0/bits/stl_construct.h:75:7: 错误:没有匹配函数调用'std::auto_ptr::auto_ptr(const std::auto_ptr& )' 75 | { ::new(static_cast(__p)) _T1(std::forward<_args>(__args)...); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~

我想知道如何将vector&lt; auto_ptr&lt;int&gt; &gt; 添加到另一个向量或列表中?

【问题讨论】:

  • 使用unique_ptr,而不是auto_ptr。这是语言有移动概念之前的残余。 (从技术上讲,残留物,因为它现在已被移除。)
  • “当我将内存管理应用到其他代码时,它很难维护” - 那么你的实际问题是什么?也许有更好的方法来解决它。
  • 还要注意在运行时会出现问题,当auto_ptr的析构函数会尝试删除source[0]source[2]等。你应该只用一个指针初始化auto_ptr是单独分配的。

标签: c++ c++11


【解决方案1】:

首先,不要使用std::auto_ptr。正如您所发现的,它不能用作向量的元素,因为它没有适当的复制构造函数。自 C++11 以来,它已被弃用,取而代之的是使用 std::unique_ptrstd::auto_ptr 已从 C++17 语言中删除。

其次,&amp;source[i] 指向的对象归source 所有。对象不属于由该表达式产生的原始指针,甚至没有办法转移它们的所有权。因此,您不能将其所有权授予智能指针。如果你这样做了,一旦这些智能指针被销毁,程序的行为将是未定义的。

如果你想要一个智能指针向量的向量,这里是一个正确的例子:

std::vector<std::unique_ptr<int>> co;
std::vector<std::vector<std::unique_ptr<int>>> all;
for (auto i : source) {
    co.push_back(std::make_unique<int>(i));
}
all.push_back(std::move(co));

奖励提示:

  • 除非您需要交换行,否则使用一维向量表示二维数组比使用向量向量更有效。
  • 不必要的动态分配可能代价高昂。鉴于向量元素本身已经在动态存储中,通常最好将对象直接存储为元素,而不是单独分配它们并存储智能指针。

【讨论】:

  • 我不确定我是否理解 unique_ptr。我认为每个 co 条目都带有指向源对应条目的指针,*all[0][0].get() 确实显示了 source[0] 的值。但是,如果您在全部构建后更改源,*all[0][0].get() 将不会相应更改。我想知道std::move是否导致问题,如果是,是否意味着unique_ptr并没有真正指向源?
  • @user1285419 does it mean unique_ptr does not really pointing to the source? 确实。唯一指针对它所指向的对象具有唯一的所有权。它不指向存储在另一个向量中的对象。
【解决方案2】:

auto_ptr&lt;T&gt; 是你永远不应该使用的东西。它具有严重且无法修复的设计缺陷。其中之一是你不能在向量中使用它。

出于某种原因,它被贬低并从 C++ 标准中删除。

使用std::unique_ptr&lt;T&gt;

【讨论】:

  • 谢谢。我尝试了 unique_ptr,它适用于一维向量,但在 vector&lt; vector&lt;unique_ptr&gt; &gt; 中仍然失败。我谷歌它,似乎使用 shared_ptr 代替工作?
  • @user 你可能需要std::move;错误发生是因为您试图复制,这是被禁止的。共享 ptr 只会隐藏问题,而不是修复它。
猜你喜欢
  • 2016-09-02
  • 1970-01-01
  • 2011-07-24
  • 2022-06-11
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多