什么是 C++ 临时对象?

2022-01-23 00:00:00 constants c++

我正在阅读 Eckel 的固定章节,并在解释 Temporaries 的部分混淆了.我能得到的是,当我们将引用传递给函数时,编译器会创建一个临时对象,它是一个 const 对象,因此即使我们将引用传递为

I was reading the constant chapter in Eckel and got mixed up in the part where Temporaries were explained . What I could get was that when we pass the reference to a function , the compiler creates a temporary which is a const object and so we can't modify it even if we pass a reference as

f(int &a){}

现在我尝试在网上查看其他一些临时人员的参考资料,结果被卡住了

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr382.htm 和

C++ 中的所有临时右值吗?

这促使我认为临时对象不仅仅是在函数内部传递引用和为其创建 const 对象.现在我可以从这两个链接中得到一些东西,但不能说我已经理解临时对象的工作、功能和使用所有的.如果有人可以解释临时人员的概念,那将非常有帮助.在此先感谢.
bruce eckel 的原始示例是:

Now I tried to look at some other references for Temporaries online and got stuck up

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr382.htm and

Are all temporaries rvalues in C++?

which prompted me that temporaries are much more than just passing references and creating const object for that inside the functions.Now I could get something out of these two links but could not say that I have understood the working , functionality and use of temporaries as a whole. It would be really helpful if someone could explain the concept of temporaries. Thanks in advance.
The original example of bruce eckel is:

// Result cannot be used as an lvalue
class X {
    int i;
    public:
    X(int ii = 0);
    void modify();
};
X::X(int ii) { i = ii; }
void X::modify() { i++; }
X f5() {
    return X();
}
const X f6() {
    return X();
}
void f7(X& x) { // Pass by non-const reference
    x.modify();
}
int main() {
    f5() = X(1); // OK -- non-const return value
    f5().modify(); // OK
    // Causes compile-time errors:
    //! f7(f5());
    //! f6() = X(1);
    //! f6().modify();
    //! f7(f6());
} ///:~

推荐答案

在 C++ 中,临时对象是编译器在各种上下文中创建的未命名对象.典型用途包括引用初始化、参数传递、表达式求值(包括标准类型转换)、函数返回和异常(抛出表达式).

In C++ temporaries are unnamed objects that compiler creates in various contexts. The typical uses include reference initialization, argument passing, evaluation of expressions (including standard type conversions), function returns, and exceptions (throw expressions).

从此 链接:

当创建临时对象来初始化引用变量时,临时对象的名称与引用变量的范围相同.如果在完整表达式(不是另一个表达式的子表达式的表达式)的求值过程中创建了一个临时对象,它会作为其求值的最后一步被销毁,在词法上包含创建它的点.

When a temporary object is created to initialize a reference variable, the name of the temporary object has the same scope as that of the reference variable. When a temporary object is created during the evaluation of a full-expression (an expression that is not a subexpression of another expression), it is destroyed as the last step in its evaluation that lexically contains the point where it was created.

完整表达式的销毁也有例外:

There are exceptions in the destruction of full-expressions:

  1. 表达式作为定义对象的声明的初始化程序出现:初始化完成后临时对象被销毁.
  2. 引用绑定到临时对象:临时对象在引用的生命周期结束时被销毁.

如果为具有构造函数的类创建了临时对象,编译器会调用适当的(匹配的)构造函数来创建临时对象.

If a temporary object is created for a class with constructors, the compiler calls the appropriate (matching) constructor to create the temporary object.

当一个临时对象被销毁并且存在析构函数时,编译器调用析构函数销毁该临时对象.当您退出创建临时对象的范围时,它会被销毁.如果引用绑定到临时对象,则临时对象在引用超出范围时被销毁,除非它在控制流中断之前被销毁.例如,由构造函数初始化程序为引用成员创建的临时对象在离开构造函数时被销毁.

When a temporary object is destroyed and a destructor exists, the compiler calls the destructor to destroy the temporary object. When you exit from the scope in which the temporary object was created, it is destroyed. If a reference is bound to a temporary object, the temporary object is destroyed when the reference passes out of scope unless it is destroyed earlier by a break in the flow of control. For example, a temporary object created by a constructor initializer for a reference member is destroyed on leaving the constructor.

在此类临时对象是冗余的情况下,编译器不会构造它们,以便创建更有效的优化代码.当您调试程序时,尤其是内存问题时,这种行为可能是一个考虑因素.

In cases where such temporary objects are redundant, the compiler does not construct them, in order to create more efficient optimized code. This behavior could be a consideration when you are debugging your programs, especially for memory problems.

让我们总结一下这样.创建这些临时对象的原因如下:

Let us summarize it this way. These temporary objects can be created for the following reasons:

  1. 使用与被初始化引用的底层类型不同类型的初始化器来初始化 const 引用.

  1. To initialize a const reference with an initializer of a type different from that of the underlying type of the reference being initialized.

存储返回用户定义类型的函数的返回值.仅当您的程序不将返回值复制到对象时,才会创建这些临时对象.因为返回值没有复制到另一个对象,所以创建了一个临时对象.创建临时变量的更常见情况是在计算表达式期间必须调用重载的运算符函数.这些重载的运算符函数返回一个用户定义的类型,该类型通常不会复制到另一个对象.

To store the return value of a function that returns a user-defined type. These temporaries are created only if your program does not copy the return value to an object. Because the return value is not copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called. These overloaded operator functions return a user-defined type that often is not copied to another object.

将转换结果存储为用户定义的类型.当给定类型的对象显式转换为用户定义类型时,该新对象将被构造为临时对象.

To store the result of a cast to a user-defined type. When an object of a given type is explicitly converted to a user-defined type, that new object is constructed as a temporary object.

让我们考虑示例:

class X {
   / / ...
public:
   / / ...
   X(int);
   X(const X&);
   ~X();
};

X f(X);

void g()
{
   X a(1);
   X b = f(X(2));
   a = f(a);
}

在这里,一个实现可能会使用一个临时对象来构造 X(2),然后再使用 X' 将它传递给 f()复制构造函数;或者,X(2) 可以在用于保存参数的空间中构造.此外,在使用 X 的复制构造函数将 f(X(2)) 的结果复制到 b 之前,可能会使用一个临时值来保存它;或者,f() 的结果可能在 b 中构造.另一方面,表达式 a=f(a) 需要 f(a) 的结果的临时值,然后将其分配给 a.

Here, an implementation might use a temporary in which to construct X(2) before passing it to f() using X’s copy-constructor; alternatively, X(2) might be constructed in the space used to hold the argument. Also, a temporary might be used to hold the result of f(X(2)) before copying it to b using X’s copy-constructor; alternatively, f()’s result might be constructed in b. On the other hand, the expression a=f(a) requires a temporary for the result of f(a), which is then assigned to a.

相关文章