bar1
和bar2
的类型之间有什么区别?
int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;
如果bar1
和bar2
都是int*
,那么在*
声明中编写指针声明符(bar2
)是否有意义?
答案 0 :(得分:44)
使用auto *
"记录意图"。只有auto *p = expr;
返回指针时才能正确推导出expr
。例如:
int f();
auto q = f(); // OK
auto *p = f(); // error: unable to deduce 'auto*' from 'f()'
答案 1 :(得分:40)
声明完全相同。 auto
与template type deduction(几乎)相同。明确地使用星形会使代码更容易阅读,并使程序员意识到bar2
是一个指针。
答案 2 :(得分:14)
在此具体示例中,bar1
和bar2
都相同。这是个人偏好的问题,但我会说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;
}
答案 3 :(得分:13)
使用{{1}}限定符时有很大差异:
{{1}}
答案 4 :(得分:10)
正如其他人所说,他们会生成相同的代码。星号是线路噪声(例如,如果&foo
被get_foo()
替换,则会更难从原始指针切换到智能指针)。如果你想要明确,那么一定要明确;但是当你使用类型推断时,只需让编译器完成它的工作。缺少星号并不意味着物体不是指针。
答案 5 :(得分: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 *
会推断出一个指向mutable的指针,我们可以通过明确地说const
来避免:
std::vector<X*> v = /* ... */;
for (const auto * p : v)
{
observe(p->foo()); // no need for a mutable *p
}