临时对象和引用是怎么回事?

发布于 2024-11-05 08:42:09 字数 581 浏览 1 评论 0原文

人们经常会看到,您无法将正常的左值引用绑定到临时对象。因此,人们经常会看到 A 类的方法采用 const A& 。当他们不想涉及复制时作为参数。然而,这样的构造是完全合法的:

double& d = 3 + 4;

因为它不会将临时对象 3 + 4 绑定到引用 d,而是使用对象 3 + 4 初始化引用。正如标准所说,仅当值不是类型或引用(或继承)时),引用不会使用通过转换或其他方式从临时对象(即另一个临时对象)获得的对象进行初始化。您可以在本例中看到:

int i = 2;
double & d = i;

这是不合法的,因为 i 不是 double 类型,也不是从 double 继承的。然而,这意味着临时变量可以绑定到引用 - 但这真的具有绑定性吗?难道不是使用复制构造函数以临时对象作为参数创建一个新对象吗?

因此,正如我所认为的,采用 const A& 的方法的要点是: param 代替 A&并不是说在第二种情况下,此类方法将无法采用 A 类型的临时对象作为参数(因为它会),而是因为它涉及复制构造函数(就像参数是 A 类型一样)。我说得对吗?

One can frequently read that you cannot bind normal lvalue reference to temporary object. Because of that one can frequently see methods of class A taking const A& as a parameter when they don't want to involve copying. However such construct is fully legal:

double& d = 3 + 4;

because it doesn't bind temporary object 3 + 4 to reference d, but rather initializes reference with an object 3 + 4. As standard says, only if value is not of type or the reference (or inherited), reference won't be initialized using object obtained from temporary object using conversion or sth (i.e. another temporary object). You can see that in this case:

int i = 2;
double & d = i;

That's not legal, because i is not of type double, nor it inherits from it. However that means, that temporaries can be bound to references - but is it really binding? Isn't it rather creating a new object using copy constructor with temporary object as its parameter?

Therefore, as I think, point of having methods taking const A& param instead of A& is not that in second case such method won't be able to take as parameter temporary object of type A (because it will), but because it involves copy constructor (just as if the parameter would be of type A). Am I right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

老娘不死你永远是小三 2024-11-12 08:42:09

首先,正如其他人所说,
双& d = 3 + 4;
合法的C++;如果你的编译器接受它,并声称
正在编译C++,这是编译器中的错误。 (注意
大多数 C++ 编译器不会声称编译 C++,除非你给出
它们是特殊选项,对于 g++,-std=c++98
示例。)

其次,这条规则的动机来自于经验。
考虑下面的例子:

void
incr( int& i )
{
    ++ i;
}

unsigned x = 2;
incr( x );  //  Implicit conversion of unsigned to int
            //  creates a temporary.
std::cout << x << std::endl;
            //  and x is still equal 2 here.

引用的原始实现没有这个
限制;你可以用一个初始化任何引用
暂时的。实际经验表明这样太容易出错,
所以需要引用 const 的限制是
介绍了。 (大约 1988 年或 1989 年,所以今天没有借口
编译器不会强制执行它。)

还要注意的是,人们经常听说将临时变量绑定到
const 引用延长了临时对象的生命周期。这是非常
误导:使用临时变量来初始化引用扩展
临时的生命周期(有某些例外),但是
如果此引用用于初始化,则生命周期不会延长
其他参考资料,即使是临时的也必然会
那些参考文献。

First, as others have said,
double& d = 3 + 4;
is not legal C++; if your compiler accepts it, and claims to
be compiling C++, it's an error in the compiler. (Note that
most C++ compilers do not claim to compile C++ unless you give
them special options, -std=c++98 in the case of g++, for
example.)

Secondly, the motivation for this rule comes from experience.
Consider the following example:

void
incr( int& i )
{
    ++ i;
}

unsigned x = 2;
incr( x );  //  Implicit conversion of unsigned to int
            //  creates a temporary.
std::cout << x << std::endl;
            //  and x is still equal 2 here.

The original implementation of references did not have this
restriction; you could initialize any reference with a
temporary. Actual experience showed this to be too error prone,
so the restriction requiring a reference to const was
introduced. (Around 1988 or 1989, so there's no excuse today
for a compiler to not enforce it.)

Note too that one often hears that binding a temporary to a
const reference extends the temporary's lifetime. This is very
misleading: using a temporary to initialize a reference extends
the temporary's lifetime (with certain exceptions), but the
lifetime is not extended if this reference is used to initialize
other references, even though the temporary is also bound to
those references.

甜`诱少女 2024-11-12 08:42:09

如果您担心函数参数列表中 const && 的含义和用途,我担心您找错了方向,因为它几乎没有什么意义。处理临时对象。

void method( Object x );

这会根据实际参数复制构造一个Object。当函数终止时,对函数内的 x 所做的任何更改都会丢失,函数的参数不会更改。

但你不想付出复制建设的成本。

void method( Object & x );

不会从实际参数复制构造一个对象,但是x引用参数,即对x所做的任何更改 函数内的操作实际上是针对参数本身完成的。

但是您不希望该方法的调用者想知道他们的参数可能会发生什么。

void method( const Object & x );

不会从实际参数复制构造对象x不能在函数内更改

您无需为复制构造函数付费,并且可以向调用者明确表示他的参数不会被篡改。

您不能将临时对象作为参数传递给第二个变体(请参阅unapersson的答案),因为不会有可更改的对象可供引用,但由于该函数大声宣告它将修改参数(因为它被声明为非常量)引用),传递临时参数作为参数无论如何都是没有意义的。

If you worry about the meaning and purpose of const & vs. & in function parameter lists, I fear you are barking up the wrong tree, as it has little to do with temporary objects.

void method( Object x );

This does copy-construct an Object from the actual argument. Any changes done to x within the function are lost when the function terminates, the argument to the function is not changed.

But you don't want to pay the cost of copy-construction.

void method( Object & x );

This does not copy-construct an Object from the actual argument, but x refers to the argument, i.e. any changes done to x within the function are really done to the argument itself.

But you don't want to have callers of the method wondering about what might happen to their arguments.

void method( const Object & x );

This does not copy-construct an Object from the actual argument, and x cannot be changed within the function.

You don't pay for the copy-constructor, and you make it clear to the caller that his argument won't be tampered with.

You cannot pass a temporary object as argument to the second variant (see unapersson's answer), because there would be no changeable object to refer to, but as that function heralds loudly that it will be modifying the argument (as it's declared a non-const reference), passing a temporary as argument is non-sensical anyway.

温柔嚣张 2024-11-12 08:42:09

双& d = 3 + 4;完全合法,事实上它不会被符合标准的编译器接受。 3+4 的结果是一个 int 类型的临时值 - 因此它只能绑定到 const 引用。

绑定引用确实具有约束力。不涉及复制。它只是延长临时对象的生命周期。

double& d = 3 + 4; is not fully legal, in fact it won't be accepted by a standard-compliant compiler. The result of 3+4 is a temporary of type int - as such it can only be bound to a const reference.

Binding references is really binding. There is no copying involved. It's simply extending the lifetime of a temporary object.

演多会厌 2024-11-12 08:42:09
void f( int & n ) {
}

int main() {
    f( 1 + 2 );
}

不涉及复制建设,但暂时不会受到约束。 g++ 的错误是:

非常量的初始化无效
类型“int&”的引用从一个
'int' 类型的右值

void f( int & n ) {
}

int main() {
    f( 1 + 2 );
}

No copy construction involved, but the temporary will not be bound. Error with g++ is:

invalid initialization of non-const
reference of type 'int&' from an
rvalue of type 'int'

独自←快乐 2024-11-12 08:42:09

引用可以由相同类型的左值初始化,3 + 4 不是左值。所以这是不合法的。 MS VC++ 编译器允许执行与对象类似的操作,但这不是标准的。

Reference can be initialized by lvalue of same type and 3 + 4 is not lvalue. So this is not legal. MS VC++ compiler permits doing something similar to your objects, but this is not in standard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文