[英]will move semantics prevent copying here?
// --- Move constructor
Matrix(Matrix&& other) throw() : data_(other.data_), Rows_(other.Rows_), Columns_(other.Columns_) { other.Rows_ = other.Columns_ = 0; other.data_ = nullptr; }
// --- Move assignment
Matrix & operator=(Matrix&& other) throw() {
using std::swap;
swap(Rows_, other.Rows_);
swap(Columns_, other.Columns_);
swap(data_, other.data_);
return *this; }
MultiplyAdd
implementation: MultiplyAdd
实现:
template <class T>
Matrix<T> MultiplyAdd(const T a,const Matrix<T> &x,const T b) {
Matrix<T> out(a*x+b);
return out; }
template <class T>
Matrix<T> MultiplyAdd(const Matrix<T> a,const Matrix<T> &x,const T b) {
Matrix<T> out(a*x+b);
return out; }
int main(){
Matrix<> x = // some initialization
auto&& temp_auto = MultiplyAdd(a,x,b);
for (int i = 1; i < N-1; i++) {
temp_auto = MultiplyAdd(temp_auto,temp2,b); }
return 0;
}
Question: Will the use of the auto
keyword in the last code snippet avoid the creation of temporaries? 问题:在最后一个代码片段中使用
auto
关键字可以避免创建临时对象吗? Before and more important inside the 'for' loop. 在“ for”循环内更重要。
Will the use of the
auto
keyword in the last code snippet avoid the creation of temporaries?在最后一个代码片段中使用
auto
关键字会避免创建临时文件吗?
No. A temporary needs to be created anyway, since temp_auto
is a reference, and there must be something that reference is bound to. 不会。无论如何,都需要创建一个临时文件,因为
temp_auto
是一个引用,并且必须绑定了一些引用。
Your odds to avoid the creation of a temporary would be higher if you had done: 如果您这样做,则避免创建临时文件的几率会更高:
auto temp_auto = MultiplyAdd(a,x,b);
In which case the compiler could perform copy/move elision and construct the result of MultiplyAdd()
directly into temp_auto
, without having to call the move constructor. 在这种情况下,编译器可以执行复制/移动
temp_auto
, temp_auto
MultiplyAdd()
的结果直接构造到temp_auto
,而无需调用move构造函数。
The reason I am talking about "odds" is that per paragraph 12.8/31 of the C++11 Standard, the compiler is entitled, but not obliged, to perform copy/move elision. 我谈论“奇数”的原因是,根据C ++ 11标准的第12.8 / 31段,编译器有权执行复制/移动省略,但没有义务。
To clarify what is going on, I will try to explain what the compiler has to do when returning an object. 为了阐明正在发生的事情,我将尝试解释编译器在返回对象时必须执行的操作。 Consider this simple function and the subsequent function call:
考虑这个简单的函数以及随后的函数调用:
X foo() { X x; /* ... */ return x; }
// ...
X y = foo();
Here, when returning x
, the compiler would have to: 在这里,返回
x
,编译器将必须:
x
(let's call it t
); x
移动构造一个临时对象(我们称其为t
); y
from t
. t
移动构造y
。 Now thanks to copy elision, the compiler is allowed to avoid the creation of the temporary t
, construct the returned object x
directly in y
, and elide both calls to the move constructor. 现在,由于有了复制省略功能,编译器可以避免创建临时
t
,直接在y
构造返回的对象x
,并将两个调用都移到move构造函数中。
On the other hand, inside the loop: 另一方面,在循环内:
temp_auto = MultiplyAdd(temp_auto,temp2,b);
You are doing an assignment . 您正在做作业 。 In our simple example, this is the equivalent of:
在我们的简单示例中,这等效于:
X foo() { X x; /* ... */ return x; }
// ...
X y;
y = foo();
Even here, when returning x
from foo()
, the compiler has to: 即使在这里,当从
foo()
返回x
时,编译器也必须:
x
from foo()
(let's call it t
again); foo()
x
移动构造一个临时对象(让我们再次将其称为t
); t
to y
. t
分配给y
。 Even in this case, the creation of a temporary can be avoided by passing directly x
(instead of t
) to the move-assignment operator that assigns to y
, although the call to the move-assignment operator cannot be elided (only calls to copy/move constructors can be elided). 即使在这种情况下,也可以通过将
x
(而不是t
)直接传递给分配给y
的移动赋值运算符来避免创建临时项,尽管不能忽略对移动赋值运算符的调用(仅调用copy / move 构造函数可以省略)。
Notice, that this is true both in your original example (where temp_auto
is a reference) and in my modified example above, where temp_auto
is an object of class type. 注意,在您的原始示例(其中
temp_auto
是引用)和我上面的修改示例中, temp_auto
是类类型的对象,这都是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.