【问题标题】:Move std::vector<T> to T*移动 std::vector<T> 到 T*
【发布时间】:2012-06-21 14:04:09
【问题描述】:

全部 我有一个遗留代码,它在草稿中做了这样的事情:

// sadly I have to use this structure
struct LegacyStruct {
  int* values;
}
LegacyStruct* LgStr;
....
    std::vector<int> vec;
    // fill vector in some way here  

    size_t sz = vec.size();
    LgStr->values = new int[sz];
    std::copy(vec.begin(), vec.end(), &LgStr->values[0]);

vec 可能很大,我需要避免将其复制到 int*。 有没有办法做到这一点? 我尝试了以下操作:

// type of new operator explained in More Effective C++
LgStr->values = new (&vec[0])int[vec.size()];

好的,values 指向 vec 内部数组的开头,但是当 vec 超出范围时它被销毁了。但我必须保留它..

&vec[0] = nullptr; // does not compile of course

所以问题是:在这种情况下是否可以应用移动语义? 或者是其他什么技巧?

【问题讨论】:

  • 你不能只处理 LgStr-> 值而不是向量吗?
  • 如果您真正想要的是从vector“释放”int 的内部动态分配数组,并将该数组的所有权转移到LegacyStructdelete[] 一段时间后来,在向量被破坏后:不,你不能。唯一的好消息是,复制到您的数组不会比首先填充向量慢,因此错过的加速机会不到 50%。
  • 只是一个快速的想法(a.k.a. HACK):您可以为std::vector(第二个模板参数)编写自己的分配器并将deallocate 实现为一个空函数。
  • @Andre 这将导致向量释放的所有内容的内存泄漏,但这不是您获得所有权的最终数组。但这可能是在正确的轨道上。

标签: c++ stl vector c++11 move-semantics


【解决方案1】:

简短的回答是不,没有任何方法可以将vector 缓冲区的所有权转移到vector 之外。

我认为您最好的选择是确保 vector 不会通过使用包装器而死:

class LegacyStructWrapper : private boost::noncopyable  // Or declare private copy constructor/copy assignment or use `= delete` in C++11.
{
private:
    std::vector<int> vec_;
    LegacyStruct wrapped_;
}

然后,只要您需要使用values,只需将其分配给&amp;vec_[0]。如果/直到您向 vector 添加更多项目,这将保持不变(因此您必须小心确保矢量调整大小不会导致问题)。

【讨论】:

  • 我建议实现或删除复制构造函数和复制赋值运算符,这样您就不会意外地指向错误的向量。
【解决方案2】:

是的,你可以这样做——用一个小技巧:

struct LegacyStruct {
  std::vector<int> backingStore;
  int* values;
  LegacyStruct(std::vector<int>& aSource) {
    // Steal memory
    aSource.swap(backingStore);
    // Set pointer
    values = &backingStore[0];
  };
}

vector.swap 操作不会复制整数。

【讨论】:

  • 确保这会起作用,但我必须将 backingStore 成员添加到 LegacyStruct (可能是我在实际代码中这样做的方式),由于其他原因,这是不可取的。无论如何,谢谢。
  • 您可以将 LegacyStruct 包装在另一个类中,并使其处理 backingStore 管理。 LegacyStruct 将保持不变。
猜你喜欢
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 2019-10-20
  • 2016-03-31
  • 2021-06-02
  • 1970-01-01
相关资源
最近更新 更多