此样本中的矢量是否复制了两次?

时间:2018-01-07 16:11:07

标签: c++ c++11

C ++书籍中的数据结构和算法分析包含图1.26中第63页的以下代码片段,用于矩阵类(某些部分被省略或截断):

#include <vector>
using namespace std;

template <typename Object>
class matrix
{
  public:
    matrix(int rows, int cols);

    matrix(vector<vector<Object>> v) : array{v} { }        
    matrix(vector<vector<Object>>&& v) : array{std::move(v)} { }

    const vector<Object>& operator[](int row) const;
    vector<Object>& operator[](int row);
  private:
    vector<vector<Object>> array;
};

matrix(vector<vector<Object>> v)构造函数中v被复制两次?签名应该是matrix(const vector<vector<Object>>& v)吗?

在勘误表中没有提到这个问题:https://users.cs.fiu.edu/~weiss/dsaa_c++4/errata.html

图书引用:

Weiss,M.A。:C ++中的数据结构和算法分析,国际版,2014,Pearson Education Limited。

2 个答案:

答案 0 :(得分:6)

是的,第一个构造函数应该v作为const &;否则,从rvalue构造时你会得到模糊的重载决策(值和rvalue引用都是同样好的匹配)。

[Live example]

但是也要回答你关于复制两次的问题:如果rvalue-reference构造函数不存在,那么将左值传递给第一个将确实产生两个副本(一次进入v,一次进入{ {1}})。传递右值可以忽略第一份副本。

事实上,只有一个这样的构造函数,这个类就可以了:

array

当使用左值初始化时,这会导致复制+移动,并且当使用右值初始化时,(elidable)移动+移动。

答案 1 :(得分:1)

是的,会有两份副本。模拟一个示例来表明这种情况是微不足道的:

#include <iostream>

struct Noisy {
    Noisy() = default;
    Noisy(const Noisy&) { std::cout << "Copy\n"; }
    Noisy(Noisy&&) { std::cout << "Move\n"; }
};

class matrix {
public:
    matrix(Noisy v) : array{v} { }
private:
    Noisy array;
};

int main() {
    Noisy n;
    matrix m{n};
}

这应该输出两次“复制”。