web-dev-qa-db-ja.com

ポインター宣言子の有無にかかわらずC ++ 11自動宣言

bar1bar2のタイプの違いは何ですか?

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

bar1bar2の両方がint*である場合、*宣言にポインター宣言子(bar2)を記述することは意味がありますか?

50
Henry Barker

宣言はまったく同じです。 autoは、(ほぼ) テンプレートタイプの推論 と同じように機能します。スターを明示的に付けると、コードが少し読みやすくなり、プログラマーにbar2はポインターです。

47
vsoftco

auto *「ドキュメントの意図」を使用します。 auto *p = expr;は、exprがポインターを返す場合にのみ正しく推定できます。例:

int f();

auto q = f(); // OK

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

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
14
danpla

この特定の例では、両方の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;
}
14

他の人が言ったように、彼らは同じコードを生成します。アスタリスクは回線ノイズです(たとえば、_&foo_がget_foo()に置き換えられた場合、生のポインターからスマートポインターへの切り替えが難しくなります)。明示的になりたい場合は、必ず明示的にしてください。ただし、型推論を使用している場合は、コンパイラに任せてください。アスタリスクの欠如は、オブジェクトがポインターではないことを意味しません。

10
Jeff Schwab

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
}
7
Kerrek SB