【问题标题】:C++: Using auto to declare classes as variables inside functionsC++:使用 auto 将类声明为函数内的变量
【发布时间】:2016-09-16 17:09:54
【问题描述】:

我正在尝试将 auto 用于我的函数中的所有局部变量。

取以下代码:

class obj 
{
  public:
  obj() {};
  obj( obj&& o ) = delete;
};

int main()
{
  obj test0;
  auto test1 = obj();

  return 0;
}

编译代码:

$ g++ --std=c++1z main.cpp
main.cpp: In function ‘int main()’:
main.cpp:13:20: error: use of deleted function ‘obj::obj(obj&&)’
   auto test1 = obj();

请注意,定义 test0 是完全可以的,但尝试执行与 test1 完全相同类型的声明是编译器错误。显然应该是编译器错误,但在这种情况下,是否意味着 obj 不能用 auto 定义?我无法控制 QT 对象时遇到了这个问题。

我仍然在使用 C++98 格式来声明变量,还是有另一种使用 auto 的方法?

谢谢!!!

【问题讨论】:

  • 使用auto test1 = obj();,您正在使用“复制初始化”。但是,obj 既不是可复制构造的(它声明了一个移动构造函数,阻止了复制构造函数的隐式生成),也不是可移动构造的(它被声明为已删除)。
  • 为防止将来出现此类陷阱,请考虑使用 C++ 的“5 规则”
  • 谢谢,我明白发生了什么以及为什么它不起作用。我的问题是, auto 可以与这样的课程一起使用吗?如果是的话怎么做。
  • 这两行根本没有做完全相同的事情。实际上我不知道在什么情况下声明 obj test0; 可能无法编译,而我可以想象很多 auto test1 = obj(); 无法编译的原因
  • @LukeDupin 哦,当然,多么愚蠢的评论......

标签: c++ c++11 move-semantics c++17


【解决方案1】:

这在 C++17 中是可以的;保证复制省略会调整规则,因此在概念上甚至不会调用移动构造函数,因此它是否被删除或无法访问都没有关系。

在那之前,如果你这么爱auto,你可以做

auto&& test1 = obj();

这会创建一个临时的 obj 对象并将其绑定到引用 test1,从而将其生命周期延长到引用的生命周期。除了少数例外,其行为与您在 C++17 中使用纯 auto 获得的行为几乎相同。

【讨论】:

  • 右值引用是否像const auto & 一样延长临时对象的生命周期?
  • @KABoissonneault 是的。
  • 天哪!!!我刚试过,这行得通。正是我想要的。感谢您实际阅读问题而不是解释为什么无法调用已删除的方法!
【解决方案2】:

该错误与auto的使用无关。

obj test1 = obj();

也不能编译。 obj() 是一个 r 值,编译器尝试移动但删除了移动构造函数。删除移动构造函数也会阻止编译器创建复制构造函数,因此它也不能复制它,因此会出错。

【讨论】:

    【解决方案3】:

    在声明中

    auto test1 = obj();
    

    编译器会尝试移动 rhs 上的对象,因为它是一个右值。它不能(因为移动 ctor 被标记为已删除)。请注意,因为移动 ctor 被删除,所以复制 ctor 也被删除,尽管编译器只会尝试移动(因为移动 ctor,即使被删除,它仍然被认为是用户定义的和it is selected as a candidate during overload resolution)。因此,您的代码无法编译。

    【讨论】:

    • 谢谢,我完全明白它在做什么,我的问题是,在这种情况下还能用auto来声明变量test1吗?
    • auto 声明很好,与编译失败无关。
    猜你喜欢
    • 2019-02-26
    • 2021-12-20
    • 1970-01-01
    • 2016-04-23
    • 2010-12-22
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多