5

“天真的”解决方案是;

std::vector<T> vector_of_objects;
vector_of_objects.reserve(vector_of_pointers.size());
for (T const * p : vector_of_pointers)
    vector_of_objects.push_back(*p);

以上看起来很麻烦,也许不是很明显。

有没有一种解决方案至少不会显着降低效率,并且可能更快更直观一点?我在想 C++11 可能有一个我不知道的解决方案......

4

6 回答 6

8

在一行中编写所有内容是否意味着更短的代码?不。

在我看来,这两行更短且更具可读性:

for (auto p : vector_of_pointers)

    vector_of_objects.emplace_back(*p);

 

函数std::for_each不比基于范围的循环短,有时由于传递 lambda 表达式而更大。

Functionstd::transform比 还要长std::for_each,但是transform这个词有利于找出下面发生的事情。

于 2013-09-27T12:07:02.897 回答
2

惯用的方法是使用std::transform

std::transform( vector_of_pointers.begin(),
                vector_of_pointers.end(),
                std::back_inserter( vector_of_objects ),
                []( T* p ) { return *p; } );

这是否比您所写的“更好”是另一个问题:它具有惯用的优势,并且可以实际命名正在发生的事情(这使代码更加清晰)。另一方面,“转换”非常非常简单,因此在循环中很容易识别,编写此类循环的新形式也使事情变得相当清楚。

于 2013-09-27T12:46:10.897 回答
2

你正在做正确的方式。另一种方法是使用内置算法库,如下所示:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main() {
    // Create a vector of pointers
    std::vector<int*> vptr;
    vptr.push_back(new int(1));
    vptr.push_back(new int(2));

    // Copy to vector of objects
    std::vector<int> vobj;
    std::for_each(vptr.begin(), vptr.end(), [&](int *n) { vobj.emplace_back(*n); });

    // Free the pointers
    std::for_each(vptr.begin(), vptr.end(), [&](int *n) { delete n; });

    // Print out the vector of objects
    std::copy(vobj.begin(), vobj.end(), std::ostream_iterator<int>(std::cout, " "));
    return 0;
}
于 2013-09-27T12:02:31.677 回答
1

不,您必须像在您的解决方案中那样调用 copy-ctor,这是没有办法的。

于 2013-09-27T11:57:23.423 回答
0
std::vector<T*> vecPointers;
std::vector<T> vecValues;

for(size_t x=0;x<vecPointers.size();x++)
{
    vecValues.push_back(*vecPointers[x]);
}

我相信如果类型 T 是自定义对象,那么您将需要为类 T 创建一个复制构造函数。

class T
{
    private:
        int someValue;
    public:
        T()
        {
        }
        T(const T &o)// copy constructor
        {
            someValue = o.someValue;
        }
        virtual ~T()
        {
        }
};
于 2013-09-27T12:03:32.690 回答
0

在我看来,真正的问题是你是否经常这样做,是否值得在一个地方编写额外的代码来清理其他地方的代码。

我可以想象写一个deref_iterator可以让你做这样的事情:

std::vector<T> vector_of_objects{
    deref_iterator(std::begin(vector_of_pointers)), 
    deref_iterator(std::end(vector_of_pointers))};

现在,我们剩下的问题是这是否真的比原始循环短。就简单的击键次数而言,它可能取决于你给事物起的名字。如果您不关心可读的名称,它可能是:

vector<T> v_o{d(begin(v_p)), d(end(v_p))};

短名称显然使它变短,但我当然不会建议他们——如果我不只是输入这个,我根本不知道它的含义。更长的名称(需要重复几次)显然会增加更多的击键,但我无法想象有人认为可读性不值得。

无论如何,它deref_iterator本身显然会占用一些代码。一个迭代器有足够的样板代码,它通常需要大约 100 行代码左右。让我们(有点武断地)决定每次使用它时都会节省一行代码。在此基础上,您必须使用它 100 次才能收支平衡。

我不确定这是否准确地描述了整个代码的特征——迭代器的代码大部分是样板代码,除了一个错字之外,它并没有太多可能真正出错的地方。在大多数情况下,只需包含正确的标头并使用它,而实际上不必查看迭代器本身的代码。

既然如此,即使代码总行数增加,我也可能会接受它作为一种改进。写它只使用一次显然是一种损失,但我认为它也不需要整整 100 次才能达到收支平衡。

于 2013-09-27T14:38:20.093 回答