【问题标题】:Proper operator (.) or (->) for accessing member of auto用于访问 auto 成员的正确运算符 (.) 或 (->)
【发布时间】:2018-04-02 23:24:43
【问题描述】:

我正在学习使用 C++11 的东西,遇到了一个我不确定如何使用 auto 的情况。考虑:

struct MyClass { double x; }
std::vector<MyClass*> myvec;
function_that_fills_vector(myvec);

//(1) this should be valid:
for(auto* item : myvec){ std::cout<< item->x <<std::endl; }

//(2) what about this?
for(auto item : myvec){ std::cout<< item.x <<std::endl; }
//(3) or this?
for(auto item : myvec){ std::cout<< item->x <<std::endl; }

也就是说,如果我知道我的auto 确实是一个指针,我可以在构造函数中明确说明它,所以我知道解引用运算符是正确的。但是如果我将myvec 更改为保存对象,(1) 将不再编译。

在 (2) 和 (3) 中,底层指针的性质是隐含的。哪个成员访问运算符(. 或 -&gt;)是正确的?如果两者都有效,是否有充分的理由使用其中一种?如果我将myvec 更改为vector&lt;MyClass&gt;,两者都会继续工作吗?

【问题讨论】:

  • #justtryitandsee
  • @LightnessRacesinOrbit 你当然是对的,但希望答案对寻找相同信息的其他人有用。
  • 说其他人也最好尝试一下

标签: c++ dereference auto


【解决方案1】:

auto 不会改变类型或类​​型的用法。

通常只有一个编译。使用它。

【讨论】:

    【解决方案2】:

    你应该使用编译器来解决这个问题!

    这是一个完整的文件:

    #include <iostream>
    #include <vector>
    
    struct MyClass {
      double x;
    };
    
    int main() {
      struct MyClass m;
      std::vector<MyClass*> myvec;
      myvec.push_back(&m);
    
      for(auto* item : myvec){ std::cout<< item->x <<std::endl; }
      for(auto item : myvec){ std::cout<< item.x <<std::endl; }
      for(auto item : myvec){ std::cout<< item->x <<std::endl; }
    }
    

    然后我们可以看一下编译器的输出:

    $ g++ fun.cc
    
    fun.cc: In function ‘int main()’:
    
    fun.cc:14:44: error: request for member ‘x’ in ‘item’, which is of pointer type ‘MyClass*’ (maybe you meant to use ‘->’ ?)
    
    for(auto item : myvec){ std::cout<< item.x <<std::endl; }
    

    如果你删除第 14 行(第二个例子),一切都会编译。换句话说:

    在第一个示例中,auto 指的是 MyClass。

    第二个它必须引用 MyClass* 但是你不能用 '.' 访问它的成员。

    在第三个中它指的是 MyClass*。

    【讨论】:

    • 我认为这意味着没有一个建议的选项适用于这两种情况(对象向量和指针向量)。我有点惊讶。
    • 这仅取决于编译器是否将类型推断为指针。它使用模板参数推导规则,其工作方式相同。比较:ideone.com/Uiuu5o
    【解决方案3】:

    这是两条相同的线。变量的类型将是 MyClass*

     //(1) this should be valid:
      for(auto* item : myvec){ std::cout<< item->x <<std::endl; }
    
      //(3) or this?
      for(auto item : myvec){ std::cout<< item->x <<std::endl; }
    

    但是这一行不应该被编译。因为变量的类型将是 MyClass* 并且您尝试通过运算符访问成员。

      //(2) what about this?
      for(auto item : myvec){ std::cout<< item.x <<std::endl; }
    

    【讨论】:

      【解决方案4】:

      类型将根据编译器可以推断出的类型来确定。来自https://en.cppreference.com/w/cpp/language/auto

      对于变量,指定要处理的变量的类型 声明将自动从其初始化程序中推导出来。

      所以基本上,它会尝试它可以推断的类型,如果找到匹配的类型,它将使用它。

      也许如果你问 auto 是什么类型,那么你可能足够关心指定类型。但是你不能使用'.'确实是有道理的。对于指针变量类型,它可以推断出任何类型都不允许这样做。

      鉴于阅读此代码的人会看到您正在使用 -> 表示法,并且可以假设您具有指针类型或 -> 运算符重载。因此,如果您想明确表示它绝对是一个指针,那么请继续。它只是在一天结束时真正有助于提高可读性,两者都一样容易编写。

      【讨论】:

        猜你喜欢
        • 2012-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-18
        • 2013-02-02
        • 1970-01-01
        • 2013-06-10
        • 2016-06-15
        相关资源
        最近更新 更多