c++ - 有没有办法将 std::vector<const T*> 转换为 std::vector<T*> 而无需额外分配?

标签 c++ c++11 vector stl

假设我有一个 Storage一些 Object s 有一个聚合指向 Objects 的指针的方法在一个 vector 中。像这样:

class Storage
{
public:
   std::vector<Object*> aggregate_some_objects(); // non-const version
   std::vector<const Object*> aggregate_some_objects() const; // const version

private:
   std::unordered_map<size_t, Object> m_objects; // data is stored 
                                                 // by-value in a non-vector container
}

一般来说,在实现 const + non-const 方法对时,有一种方法可以避免复制粘贴,方法是在 const_cast 的帮助下调用其中一个方法对。 .然而,这是不可能的,因为方法的返回类型不同。

此处避免复制粘贴的最直接方法是调用 const来自非 const 的版本版本并使用返回的 std::vector<const T*>填充一个单独的 std::vector<T*> .然而,这将导致至少 2 个堆分配(每个 vector 一个)。我想避免与第二个 vector 相关的分配。

我想知道是否有办法写类似的东西

template <typename T>
std::vector<T*> remove_const_from_vector_of_ptrs(std::vector<const T*>&& input)
{
   std::vector<T*> ret;
   // do some magic stuff here that does not involve
   // more memory allocations
   return ret;
}

因此,允许写入

std::vector<const Object*> Storage::aggregate_some_objects() const
{
   // non-trivial implementation
}

std::vector<Object*> Storage::aggregate_some_objects() 
{
   auto objects = const_cast<const Storage*>(this)->aggregate_some_objects();
   return remove_const_from_vector_of_ptrs(std::move(objects));
}

std::vector 中没有“释放”方法(例如 std::unique_ptr),它允许转移内存所有权 - 并且有一个很好的理由,所以我认为这是不可能的。

我也明白,如果可能的话,这将是一个通常应该避免的危险操作,就像 const_cast .但在这种情况下谨慎使用似乎比复制粘贴更有益。

编辑: 对“额外”分配的含义进行了澄清并更改了 Storage::aggregate_objects()Storage::aggregate_some_objects()为了更好地表明这些方法的实现比基于范围的循环更复杂 - 因此希望避免复制粘贴实现。

最佳答案

简短的回答是:不。 std::vector<Object*>std::vector<const Object*>是两个不同的、独立的类。它们彼此不同,如 class A来自 class B .人们常常认为,仅仅因为它们都以 std::vector 开头,它们在某种程度上彼此相关。这不是真的,因此没有办法“就地”将一个转换为另一个。这些 vector 类中的每一个都拥有它们相应的内部data() ,并且不会心甘情愿地把它交给其他一些奇怪的类(class)。

答案仍然是否定的,但在许多情况下,可以解决此问题以避免手动重复代码。事实上,在大多数此类情况下,代码重复是不可避免的,而能做的最好的事情就是避免手动重复代码。

一种常见的方法是让常量和可变类方法成为单个共享私有(private)模板的外观:

// Header file:

class Storage {

public:

    std::vector<const Object*> aggregate_objects() const;

    std::vector<Object*> aggregate_objects();

private:

    template<typename v_type> void make_aggregate_objects(v_type &v) const;
};

// In the translation unit:

template<typename v_type> void Storage::make_aggregate_objects(v_type &v) const
{
     // Now, create 'v' here... v.reserve(), v.push_back(), etc...
}

std::vector<const Object*> Storage::aggregate_objects() const
{
     std::vector<const Object *> v;

     make_aggregate_objects(v);

     return v;
}

std::vector<Object*> Storage::aggregate_objects()
{
     std::vector<const Object *> v;

     make_aggregate_objects(v);

     return v;
}

编译器仍然会生成两个几乎相同的代码块,但至少不是你来做所有的输入。

另一种类似的方法是将 lambda 传递给模板函数,而不是传递 vector 对象,而私有(private)模板函数使用 lambda 函数作为回调来构造返回的 vector 。通过一些类型删除,以及来自 std::function 的一些帮助,私有(private)类方法可以变成普通方法,而不是模板方法。

关于c++ - 有没有办法将 std::vector<const T*> 转换为 std::vector<T*> 而无需额外分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37764052/

相关文章:

c++ - 为什么用 enable_if 编译错误

c++ - 如何将所有指针从一个 vector 移动到另一个 vector ?

c++ - async_read_until 的 Lambda 不初始化长度参数

c++ - vector 的返回 vector

vector - 在 Rust 中初始化向量的向量

C++ 数组,在运行时设置数组大小

c++ - gSOAP 到 WCF。应用程序/soap+xml;字符集=utf-8

c++ - 舍入错误在 DFT 中给出不正确的结果?

c++ - std::vector 中的自定义分配器

arrays - 持有排序数组-反向排序输入情况