我正在学习使用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
实际上是一个指针,我可以在构造函数中明确它,所以我知道dereference运算符是正确的。但如果我改变myvec
来保存对象,(1)将不再编译。
在(2)和(3)中,底层指针的性质是隐含的。哪个成员访问运算符(.
或->
)是正确的?如果两者都有效,是否有充分理由使用其中一种?如果我将myvec
改为vector<MyClass>
,两者都会继续有效吗?
auto
不会改变该类型的类型或用法。
通常只有一个编译。用那个。
您应该使用编译器来解决这个问题!
这是一个完整的文件:
#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 *。
这是两条相同的线。变量的类型将是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; }
类型将根据编译器可以推导出的类型来确定。来自https://en.cppreference.com/w/cpp/language/auto
对于变量,指定将从其初始化程序自动推导出正在声明的变量的类型。
所以基本上,它会尝试它可以推断出的类型,如果找到匹配的类型,它将使用它。
也许如果你问的是汽车推断出的类型,那么你可能会非常关心指定类型。但是你不能使用'。'确实有意义。对于指针变量类型,没有可以推导出的类型允许这样做。
无论阅读此代码的人会看到您使用的是什么 - >表示法并且可以假设您有指针类型或 - >运算符重载。因此,如果你想要明确它肯定是一个指针然后继续。它只能在一天结束时帮助提高可读性,两者都很容易编写。