【问题标题】:Pushing vector<double> onto vector<vector<double>>将向量<double> 推到向量<vector<double>>
【发布时间】:2012-10-02 13:13:04
【问题描述】:

所以,我有这种情况:

vector<vector<double>> myVector; 
myVector.resize(somePreviousObject.size());
for(int i = 0; i < myVector.size(); i++)
{
    vector<double> tempVector;
    //Do some stuff that fills tempVector, in a loop
    //After loop:
    myVector[i].push_back(tempVector);
}

但是,这会产生一个编译错误,说明:

no matching function for call to 'std:;vector<double, std::allocator<double > >::push_back(std::vector<double, std::allocator<double> >&)'
...stl_vector.h:733 note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = double, _Alloc = std::allocator<double>]

我意识到使用向量的向量对性能不友好,但它仍然应该编译和执行,对吗?为什么不呢?

感谢您的帮助。

【问题讨论】:

    标签: c++ vector compiler-errors


    【解决方案1】:

    在表达式中:

    myVector[i].push_back(tempVector);
    

    子表达式myVector 是std::vector&lt;std::vector&lt;double&gt;&gt;,myVector[i] 是std::vector&lt;double&gt;&amp;,并且该向量上的push_back 需要double,而不是std::vector&lt;double&gt;。

    您似乎想将第 i 元素设置为 tempVector,如果是这种情况,您应该这样做(假设您不需要 tempVector 之后本声明):

    myVector[i].swap(tempVector);
    

    (虽然myVector[i] = tempVector; 具有相同的净效果,但它会更昂贵,因为它会分配和复制所有内容。swap 将移动tempVector 的内容几乎免费进入myVector[i](三指针交换))

    我知道有人会过来建议使用myVector[i] = std::move(tempVector),这在 C++11 中也可以,但在 C++03 中不可用。两者的区别在于swap的情况下myVector[i]的原始内容在运行后保证在tempVector里面(这里myVector[i]是空的,所以没关系)。另一方面,myVector[i] = std::move(tempVector); 之后的tempVector 的状态在标准中是未定义的,它可以将向量留空,或者可以交换它或者......唯一的保证是tempVector 对象可以被销毁搬家后。

    【讨论】:

    • 我认为利用swap 进行值的恒定时间分配(在这种情况下你想丢弃源)可以很好地隐藏在一个小助手对象中,它在析构函数。 container_update&lt;std::vector&lt;int&gt;&gt; tmp(myVector[i]); 之类的东西在内部维护一个 std::vector 并在 tmp 对象超出范围时将其与 myVector[i] 交换。
    • @FrerichRaabe:我理解你的意思,但我不同意这种观点。代码应该清楚它的作用。如果操作更复杂,我会添加一个助手,但我认为没有任何意义。另请注意,swap 具有其他副作用(tmpVector 更改),仅查看函数调用可能并不明显。最后,我会发现通过完全删除代码并使用引用更容易阅读:std::vector&lt;double&gt; &amp; tempVector = myVector[i];(但这意味着即使没有到达旧的分配行,容器也会更新)
    • 啊,我真的很傻。我将坚持使用 C++03 交换方法而不是 C++11 移动,因为我不能保证用户群将拥有 C++11。感谢您的帮助!
    • @DavidRodríguez-dribeas:仅使用引用也是我的第一个想法,但是您确实会丢失提交语义(如果您在中间开始出现异常,这可能会成为一个问题)。至于辅助对象 - 我完全同意,代码应该清楚 what 它的作用。原始的swap 行是如何 执行它,但what 它执行代码的目的是更新向量myVector[i] 的值。辅助对象的另一个好处是交换的源(在这种情况下被清空)在交换之后不能再被访问。
    • @FrerichRaabe:它所做的并不是真正更新元素,而是移动临时向量到容器中。在 C++11 中,即std::move,在 C++03 中,惯用方式是交换,如 copy-and-swap 习惯用法。 container_update&lt;...&gt; tmp(...); tmp.push_back(x); 是修改原始容器还是仅在超出范围时修改?它会复制或移动元素吗?这些是你的抽象隐藏的细节。
    【解决方案2】:

    要么是

    myVector[i] = tempVector;
    

    或

    myVector.push_back(tempVector);
    

    由于您事先调整了矢量的大小,我假设您想要第一个版本。

    在您的代码中,请记住 myVector[i] 本身就是 vector&lt;double&gt;,这就是它不起作用的原因。

    【讨论】:

    • @DavidRodríguez-dribeas 以前从未使用过。比=好吗?
    • 它不会分配空间并将所有内容从tempVector复制到myVector[i],而是移动内容(即不分配内存,不复制,只是三个指针交换)。看我的回答。
    【解决方案3】:
    vector<vector<double>> myVector;  
    

    应该是:

    vector<vector<double> > myVector;  
    

    然后

    myVector[i].push_back(tempVector); 
    

    应该是

    myVector.push_back(tempVector); 
    

    【讨论】:

    • 第一个区别取决于编译器。 C++11 使该语法有效,因此我们不能再 bash VS 接受无效语法。
    猜你喜欢
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 2011-03-07
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多