【问题标题】:How to create temporary object in C++如何在 C++ 中创建临时对象
【发布时间】:2015-05-13 08:50:42
【问题描述】:

我有以下代码。

class A {
 public:
  A(int) {
  }
};

int a;
int main() {
  A(a);  // Line 'a
  return 0;
}

我想在'a 行做的是用构造函数A::A(int) 创建一个临时A。我知道它会立即毁灭。这就是我想要的。但似乎编译器正在执行与A a 等效的操作,将变量a 定义为类A 并使用构造函数A::A() 对其进行初始化。当然它不存在,因此编译器错误。

但是,如果我将代码更改为以下内容。

class A {
 public:
  A(int) {
  }
};

void f(A) {
}

int a;
int main() {
  f(A(a));
  return 0;
}

现在可以正常使用了。编译器构造一个临时的A,并用它来调用f

为什么A(a) 在两种情况下都不同?它是如何在标准中说明的或出于某种模糊的原因?如何像第一个代码示例那样构造一个临时对象?

【问题讨论】:

  • 你仍然需要给它一个名字。试试A temp(a);
  • 您是否尝试过在第一个示例中使用A{a};,因为它是最麻烦的解析示例?您也可以尝试使用 void-cast:static_cast<void>(A(a));
  • @jakber 我希望temp 在此声明后立即销毁。如果我给它一个名字,它就不会发生。
  • jakber:不,那么它将一直存在到范围结束。 Hot Pxl 希望它在语句结束时破坏。
  • 请注意,如果您使用数字初始化A,它会起作用,并且如果您将int a;放在main中,则重新定义a会出错。

标签: c++


【解决方案1】:

这是“可以成为声明的一切都是声明”规则的另一个实例。 [stmt.ambig]/p1:

涉及表达式语句的语法存在歧义 和声明:具有函数样式的表达式语句 显式类型转换(5.2.3)作为其最左边的子表达式可以是 与 declaration 没有区别,其中第一个 declarator( 开头。在这些情况下,声明是一个声明

该标准提供了以下示例:

假设 T 是一个简单类型说明符

T(a)->m = 7;       // expression-statement
T(a)++;            // expression-statement
T(a,5)<<c;         // expression-statement
T(*d)(int);        // declaration
T(e)[5];           // declaration
T(f) = { 1, 2 };   // declaration
T(*g)(double(3));  // declaration

在上面的最后一个例子中,g,它是一个指向T的指针,被初始化了 到double(3)。出于语义原因,这当然是格式错误的,但是 不影响句法分析。

还有:

class T {
// ...
public:
    T();
    T(int);
    T(int, int);
};

T(a);          // declaration
T(*b)();       // declaration
T(c)=7;        // declaration
T(d),e,f=3;    // declaration
extern int h;
T(g)(h,2);     // declaration

消除歧义的最简单方法可能是额外的一组括号。 (A(a)); 无疑是一个表达式语句

【讨论】:

  • 我认为这个答案如果包含关键字“最令人烦恼的解析”会更好,可能带有维基百科的链接。
  • A { a } 怎么样; ?
【解决方案2】:

我想不出一种方法来创建一个临时而不在某些调用中使用它,就像你对函数所做的那样。

为什么不想创建一个命名变量呢?考虑到您尝试声明它的方式,它的生命周期将与您的“临时”完全相同。

如果你真的想控制你的对象的销毁,你总是可以将它封装在一个块中:{ A tmp(a); } // temporary A object


问题是……我不明白这样做的意义。为什么要创建一个临时对象而不使用它?这通常意味着您的对象创建或销毁有一些您想要触发的副作用。这是一个非常糟糕的主意!您应该将副作用移到一个函数中并简单地调用它。

【讨论】:

  • 你说得对,我应该使用函数。我只是好奇为什么临时不能工作。我从一些 RTTI 代码中得到了这个想法。但我想这毕竟是个坏主意。
  • @VincentRobert 我同意你的观点,我也想知道像 function( A() )return A() 这样的操作是否会影响传递给函数或由函数返回的副本。我的意思是对象是在复制之前还是之后销毁的?如果对象在复制之前被销毁,您将在函数中或作为返回值获得对象的统一化副本。
猜你喜欢
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多