bar1
とbar2
のタイプの違いは何ですか?
int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;
bar1
とbar2
の両方がint*
である場合、*
宣言にポインター宣言子(bar2
)を記述することは意味がありますか?
宣言はまったく同じです。 auto
は、(ほぼ) テンプレートタイプの推論 と同じように機能します。スターを明示的に付けると、コードが少し読みやすくなり、プログラマーにbar2
はポインターです。
auto *
「ドキュメントの意図」を使用します。 auto *p = expr;
は、expr
がポインターを返す場合にのみ正しく推定できます。例:
int f();
auto q = f(); // OK
auto *p = f(); // error: unable to deduce 'auto*' from 'f()'
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
この特定の例では、両方のbar1
およびbar2
同じだ。個人的な好みの問題ですが、bar2
は読みやすいです。
ただし、これは 例 に見られるように、参照には当てはまりません。
#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;
}
他の人が言ったように、彼らは同じコードを生成します。アスタリスクは回線ノイズです(たとえば、_&foo
_がget_foo()
に置き換えられた場合、生のポインターからスマートポインターへの切り替えが難しくなります)。明示的になりたい場合は、必ず明示的にしてください。ただし、型推論を使用している場合は、コンパイラに任せてください。アスタリスクの欠如は、オブジェクトがポインターではないことを意味しません。
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-correctnessに役立ちます。次の例を考えてみましょう。この例では、コンテナには可変ポインタへのポインタが含まれていますが、constアクセスのみが必要です。ただauto *
は、可変を指すポインターを推測します。これは、const
を明示的に指定することで回避できます。
std::vector<X*> v = /* ... */;
for (const auto * p : v)
{
observe(p->foo()); // no need for a mutable *p
}