【问题标题】:C++ Error: no matching function for call to 'std::vector<int>::swap(std::vector<int>)'C++ 错误:没有用于调用 'std::vector<int>::swap(std::vector<int>)' 的匹配函数
【发布时间】:2016-10-29 01:10:21
【问题描述】:

我正在阅读有关 std::vector 的博客。请参阅此website 中的交换内容部分。


基本上,它说swap() 方法的一个常见应用是强制向量释放它持有的内存。但是在我运行下面的代码之后,我得到了错误Error: no matching function for call to 'std::vector&lt;int&gt;::swap(std::vector&lt;int&gt;)'|。哪里出了问题?


#include <iostream>
#include <vector>

int main( )
{
    std::vector<int> v;
    v.push_back(1); v.push_back(2);
    v.clear();
    v.swap(std::vector<int>(v));
    return 0;
}

【问题讨论】:

    标签: c++ vector swap


    【解决方案1】:

    std::vector::swap 的参数类型是非常量左值引用(即vector&amp;)。但是std::vector&lt;int&gt;(v)是一个临时对象,不能绑定非const引用。

    也就是说,当使用“交换技巧”时,你应该把临时放在左边:

    std::vector<int>(v).swap(v);
    

    从 C++11 开始,您可以使用 std::vector::shrink_to_fit 请求移除未使用的容量;注意这是一个非绑定请求,效果取决于实现。

    【讨论】:

    • 博客好像有这个错误。一个后续问题,博客说临时向量是使用复制构造函数创建的,但我认为std::vector&lt;int&gt;(v) 只是v 的重铸,就像我们可以将数组转换为std::vector 并将浮点数转换为虽然类型在演员表之前和之后是相同的(看起来很奇怪)。我想知道我是对的吗?
    • @Nicholas 是的,对于std::vector&lt;int&gt;(v),需要构建一个临时的vector,复制ctor 将用于它。当您使用数组构造向量时,将使用适当的ctor来构造向量。是的,这是强制转换的,本质上将调用适当的构造函数来构造 std::vector
    • 不,您不应该使用复制构造函数。这是对内存的浪费,尤其是在原始向量中有大量项目的情况下。而且它不会为您带来任何好处,因为您会将原始数据的 副本 交换回原始向量,从而违背了本练习的全部目的。您需要默认构造要与之交换的临时对象,例如:std::vector&lt;int&gt;().swap(v); 这样,原始向量会释放其分配内存的所有权,而临时向量会获得所有权,因此当临时向量消失时它会被释放范围,
    • @RemyLebeau 我觉得OP只想释放容量?
    • @songyuanyao:这就是我的意思。如果您使用 copy-constructed 临时向量,它将复制数据,保持原始数据不变,然后交换将仅切换内存指针。原始向量将以与开始时相同的数据结束,只是位于新的内存地址。但是如果你使用 default-constructed 临时向量,原始向量将不再分配任何内存,临时向量将释放原始内存。
    【解决方案2】:

    std::vector::swap() 不接受临时对象作为输入。它将输入对象作为非常量左值引用(因此它可以修改输入对象)。 非 const 左值引用 不能绑定到临时对象(只有 const 左值引用右值引用可以这样做),这就是您得到编译器错误的原因。

    您还应该使用 default 构造函数而不是 copy 构造函数,以确保原始 vector 与空状态交换,而临时 @987654323 @ 假定原始分配内存的所有权。

    使用您的原始代码,您需要声明另一个 vector 变量以与之交换:

    std::vector<int> temp;
    v.swap(temp);
    

    否则,将两个对象的顺序调换一下,这是首选方法:

    std::vector<int>().swap(v);
    

    【讨论】:

    • 假设n=v.capacity(); 紧跟在v.clear(); 行之后,那么您是否建议std::vector&lt;int&gt;(v).swap(v); 在切换内存指针时,仍然有v 占用n 内存?但是std::vector&lt;int&gt;().swap(v); 也将v 的容量重置为x,其中xstd::vector&lt;int&gt;() 分配的内存数量?在大多数情况下,x 预计会小于n
    • 我分别尝试了std::vector&lt;int&gt;().swap(v); std::cout &lt;&lt; v.capacity() &lt;&lt; v.size();std::vector&lt;int&gt;(v).swap(v); std::cout &lt;&lt; v.capacity() &lt;&lt; v.size();。但是对于两者我都得到了00?看来我之前的评论有误?
    • @Nicholas 复制构造函数不保证紧凑性。仅需要复制元素,因此size() 将匹配原始元素,但新的capacity()至少 size() 但可以更大。这取决于实现
    • @Nicholas after v.clear(), v.size() 为 0。复制构造函数很可能不会分配任何内容,因为它不复制任何内容。所以vector&lt;int&gt;(v).swap(v) 在这种情况下可能等同于vector&lt;int&gt;().swap(v),但这不是保证。这也是为什么复制构造函数不是压缩非空向量的可靠方法的原因。
    • 感谢您的详细解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2021-05-05
    相关资源
    最近更新 更多