4

我有一个对向量,我需要将它们线性复制到整数向量。我的以下代码运行良好,但我不确定考虑到 C++ 中的结构填充问题是否安全。

std::vector < std::pair<int, int> > test_vector;
for (int i=0;i<5;i++) {
    test_vector.push_back(std::make_pair(i,i*5));
}
std::vector<int> int_vec(test_vector.size() * 2);
std::copy(reinterpret_cast<int*>(&(*test_vector.begin())),reinterpret_cast<int*>(&(*test_vector.end())),int_vec.begin());

现在,我的问题是——上面的代码安全吗?如果没有,是否有一种优雅的方法可以在不编写循环的情况下做到这一点?

4

4 回答 4

5

std::transform 和一个 lambda 函数怎么样?

std::vector<int> v;
std::transform(test_vector.begin(), test_vector.end(), std::back_inserter(v), 
               [&v](const std::pair<int, int> &p) 
               { v.push_back( p.first);
                 return p.second ;});

如果您不能使用 C++11,并且可能“讨厌”使用循环进行线性复制

您可以使用函子,如:

struct X{
    X(std::vector<int> &x) :v(x){}
    int operator () (const std::pair<int, int> &p)
    {
        v.push_back(p.first);
        return p.second;
    }
    std::vector<int> &v;
};

std::vector<int> v; //Final vector

std::transform(test_vector.begin(), 
               test_vector.end(), 
               std::back_inserter(v), 
               X(v));

std::vector<int> ::iterator it;

for(it=v.begin() ; it!=v.end() ;++it)
  std::cout<<*it<<" ";
于 2013-10-09T05:41:39.280 回答
1

Areinterpret_cast通常是坏消息。std::for_each在目标向量中保留足够的空间,然后调用对的源向量,然后将函数/lambda push_back 第一个和第二个都放入目标向量中,难道不是更好吗?

于 2013-10-09T05:26:21.113 回答
1

你不需要对这个问题有任何幻想。一个简单的 for 循环就可以了,特别是如果你不能使用 C++11

std::vector < std::pair<int, int> > test_vector;
std::vector<int> int_vec; int_vec.reserve(test_vector.size() * 2);
for (std::vector < std::pair<int, int> >::const_iterator it = test_vector.begin(), end_it = test_vector.end(); it != end_it; ++it)
{
    int_vec.push_back(it->first);
    int_vec.push_back(it->second);
}
于 2013-10-09T15:33:21.693 回答
1

您担心结构填充问题是正确的,但我认为您还没有真正面对您的代码所做的核心假设:

我可以将 astd::pair<int, int>视为两个整数的数组,其中.first第一个元素是数组.second中的第二个元素吗?

从“正确性”的角度来看,我会说“不”。您已经确定了填充问题,但还有字段的顺序。确实不能保证它.first的内存地址低于.second.

从“实用”的角度来看,我会很惊讶你的代码不起作用。[编辑:尼尔指出了一个存在填充问题的具体例子;让我很惊讶。除了“糟糕的形式”之外,我现在认为代码在实践中被破坏了。]

至于解决方案,您可以使用for_each自定义操作来推送该对的两个元素(未经测试的代码)

struct action {
    action ( vector<int> & target ) : t_(target) {}
    void operator () ( const pair &p ) const 
        { t_.push_back(p.first); t_.push_back(p.second); }
private:
    vector<int> &t_;
}

for_each ( test_vector.begin(), test_vector.end(), action(v));
于 2013-10-09T15:27:50.563 回答