【问题标题】:C++11 auto declaration with and without pointer declarator带和不带指针声明符的 C++11 自动声明
【发布时间】:2016-04-06 05:57:49
【问题描述】:

bar1bar2的类型有什么区别?

int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;

如果bar1bar2 都是int*,那么在bar2 声明中写入指针声明符(*)是否有意义?

【问题讨论】:

    标签: c++ c++11 auto variable-declaration


    【解决方案1】:

    声明完全相同。 auto 的工作方式(几乎)与 template type deduction 相同。明确地添加星号使代码更易于阅读,并使程序员意识到bar2 是一个指针。

    【讨论】:

      【解决方案2】:

      使用auto *“文件意图”。而auto *p = expr;只有在expr返回指针时才能正确推导出来。示例:

      int f();
      
      auto q = f(); // OK
      
      auto *p = f(); // error: unable to deduce 'auto*' from 'f()'
      

      【讨论】:

      • 是的,但是下一个运算符 & 被重载以返回一个 notnull 或 const 传播智能指针,然后自动 * 中断。
      • 我同意记录意图,例如,如果您停止将其用作指针,则客户端代码中关于应该如何处理返回类型的一些假设可能不太有效。所以这种写法可以避免重构时的bug。
      【解决方案3】:

      使用const 限定符时有很大的不同:

      int i;
      
      // Const pointer to non-const int
      const auto ip1 = &i; // int *const
      ++ip1; // error
      *ip1 = 1; // OK
      
      // Non-const pointer to const int
      const auto* ip2 = &i; // int const*
      ++ip2; // OK
      *ip2 = 1; // error
      

      【讨论】:

        【解决方案4】:

        在此特定示例中,bar1bar2 是相同的。这是个人喜好问题,虽然我会说bar2 更容易阅读。

        但是,这不适用于在此 example 中看到的引用:

        #include <iostream>
        using namespace std;
        
        int main() {
            int k = 10;
            int& foo = k;
            auto bar = foo; //value of foo is copied and loses reference qualifier!
            bar = 5; //foo / k won't be 5
            cout << "bar : " << bar << " foo : " << foo << " k : " << k << endl;
            auto& ref = foo;
            ref = 5; // foo / k will be 5
            cout << "bar : " << bar << " foo : " << foo << " k : " << k;
            return 0;
        }
        

        【讨论】:

          【解决方案5】:

          正如其他人所说,他们会生成相同的代码。星号是线路噪声(例如,如果&amp;foo 曾经被get_foo() 替换,则使从原始指针切换到智能指针变得更加困难)。如果你想明确,那么一定要明确;但是当您使用类型推断时,只需让编译器完成它的工作。缺少星号并不意味着对象不是指针。

          【讨论】:

          • 我认为括号中的评论值得更加强调。即使在其他人给出的简单示例中,添加* 可能会使代码更具可读性,但会使维护更加困难。我个人认为auto 的主要好处是易于维护,甚至比减少打字或提高可读性更重要。
          【解决方案6】:

          就 C++ 代码的解释而言,这无关紧要;你可以写任何你想要的。但是,存在样式和可读性问题:通常,您不应该在类型别名中隐藏指针、引用和 CV 限定符,甚至可能是智能指针,因为这会使读者更难理解这是怎么回事。类型别名应该封装语义相关的类型内容,而限定符和修饰符应该保持可见。所以更喜欢以下:

           using Foo = long_namespace::Foobrigation<other_namespace::Thing>;
           using MyFn = const X * (int, int);
          
           std::unique_ptr<Foo> MakeThatThing(MyFn & fn, int x)   // or "MyFn * fn"
           { 
               const auto * p = fn(x, -x);
               return p ? p->Create() : nullptr;
           }
          

          不要说:

          using PFoo = std::unique_ptr<Foo>;   // just spell it out
          using MyFn = int(&)(int, int);       // unnecessary; & is easy to spell
          auto p = fn(x, -x);                  // Don't know that p is a pointer
          

          还要注意,引用限定符(与指针不同)真正改变了正在声明的变量的类型,因此它们不是可选的:

          X & f();
          auto a = f();    // copy!
          auto & b = f();  // b is the same as the return value of f()
          

          最后,添加明确的 const 指针限定可以帮助 const 正确性。考虑下一个示例,其中容器包含指向可变的指针,但我们只需要 const 访问。只是auto * 会推断出一个指向可变的指针,我们可以通过明确地说const 来避免这种情况:

          std::vector<X*> v = /* ... */;
          for (const auto * p : v)
          {
              observe(p->foo());   // no need for a mutable *p
          }
          

          【讨论】:

          • 由于MyFn 返回类型是intauto*p = fn(x, -x) 不会编译(感谢*,否则我们应该等待p-&gt;Create() 的错误):-)。跨度>
          • @Jarod42:是的,我使用的不同实体太少了。固定。
          猜你喜欢
          • 1970-01-01
          • 2015-05-02
          • 1970-01-01
          • 2019-03-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多