C ++ 11:移动/复制构造模糊? [英] C++11: Move/Copy construction ambiguity?

查看:186
本文介绍了C ++ 11:移动/复制构造模糊?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 11中,我们可以定义复制和移动构造函数,但同时允许在同一个类上?如果是,你如何消除他们的用法?例如:

In C++11 we can define copy and move constructors, but are both allowed on the same class? If so, how do you disambiguate their usage? For example:

Foo MoveAFoo() {
  Foo f;
  return f;
}

以上是副本吗?移动?我如何知道?

Is the above a copy? A move? How do I know?

推荐答案

通常不会由于 RVO

如果无法执行该优化,被返回的对象超出范围(并且将在之后被销毁)。如果无法移动,则会被复制。如果它不能被复制,它将无法编译。

If that optimisation can't be performed, then it will be a move, because the object being returned is going out of scope (and will be destroyed just after). If it can't be moved, then it will be copied. If it can't be copied, it won't compile.

移动构造函数的整体点是,当一个副本将由一个对象即将被销毁,则通常不必制作整个副本,并且可以将资源从停止对象移动到正在创建的对象

The whole point of move constructors is that when a copy is going to be made of an object that is just about to be destroyed, it is often unnecessary to make a whole copy, and the resources can be moved from the dying object to the object being created instead.

您可以根据要移动/复制的对象发生什么情况,告知何时调用复制或移动构造函数。它是否即将超出范围并被毁灭?如果是这样,移动构造函数将被调用。如果没有,复制构造函数。

You can tell when either the copy or move constructor is going to be called based on what is about to happen to the object being moved/copied. Is it about to go out of scope and be destructed? If so, the move constructor will be called. If not, the copy constructor.

当然,这意味着你可以在同一个类中有一个移动构造函数和复制构造函数。

Naturally, this means you may have both a move constructor and copy constructor in the same class. You can also have a copy assignment operator and a move assignment operator as well.

更新:也可以使用此功能。不清楚到什么时候移动构造函数/赋值运算符被调用与普通拷贝构造函数/赋值运算符。如果我理解正确,如果一个对象用xvalue(eXpiring值)初始化,则调用move constructor。标准的§3.10.1说

Update: It may be unclear as to exactly when the move constructor/assignment operator is called versus the plain copy constructor/assignment operator. If I understand correctly, the move constructor is called if an object is initialised with an xvalue (eXpiring value). §3.10.1 of the standard says


一个xvalue(一个eXpiring值)也指一个对象,通常在
它的生命周期的结束(以便其资源可以移动,对于
示例)。 xvalue是某些种类的表达式
涉及右值引用(8.3.2)的结果。 [示例:调用
的结果是返回类型为右值引用的函数是xvalue。 -end
example]

An xvalue (an "eXpiring" value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue reference is an xvalue. —end example ]

标准§5的开头说:


[注意:如果表达式是一个xvalue:

[ Note: An expression is an xvalue if it is:


  • 调用
    函数,无论是隐式还是显式,其返回类型是对对象类型的
    rvalue引用。

  • 转换为对$ b $的右值引用b对象类型

  • 类成员访问表达式指定
    非引用类型的非静态数据成员,其中对象
    表达式是x值,或

  • a。*
    中的指针到成员表达式,第一个操作数是xvalue,第二个操作数是指向数据成员的
    指针。

  • the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,
  • a cast to an rvalue reference to object type,
  • a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or
  • a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.

一般来说,此规则的效果是
命名的rvalue引用被视为lvalues和未命名的rvalue
引用对象被视为xvalues;
函数的右值引用被视为无论是否命名的左值。 -end note]

In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not. —end note ]






例如,如果NRVO可以完成,像这样:


As an example, if NRVO can be done, it's like this:

void MoveAFoo(Foo* f) {
    new (f) Foo;
}

Foo myfoo; // pretend this isn't default constructed
MoveAFoo(&myfoo);

如果无法执行NRVO,但 Foo 是可移动的,那么你的例子是这样的:

If NRVO can't be done but Foo is moveable, then your example is a little like this:

void MoveAFoo(Foo* fparam) {
    Foo f;

    new (fparam) Foo(std::move(f));
}

Foo f; // pretend this isn't being default constructed
MoveAFoo(&f);

如果它不能移动但可以复制, >

And if it can't be moved but it can be copied, then it's like this

void MoveAFoo(Foo* fparam) {
    Foo f;

    new (fparam) Foo((Foo&)f);
}

Foo f; // pretend this isn't default constructed
MoveAFoo(&f);

这篇关于C ++ 11:移动/复制构造模糊?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆