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。
答案 0 :(得分:6)
是的,第一个构造函数应该v
作为const &
;否则,从rvalue构造时你会得到模糊的重载决策(值和rvalue引用都是同样好的匹配)。
但是也要回答你关于复制两次的问题:如果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};
}
这应该输出两次“复制”。