bar1
とbar2
の違いは何ですか?ポインタ宣言子の有無にかかわらずC++ 11の自動宣言
int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;
bar1
とbar2
両方がint*
であれば、それはbar2
宣言でポインタ宣言子(*
)を書くために理にかなっているのでしょうか?
bar1
とbar2
の違いは何ですか?ポインタ宣言子の有無にかかわらずC++ 11の自動宣言
int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;
bar1
とbar2
両方がint*
であれば、それはbar2
宣言でポインタ宣言子(*
)を書くために理にかなっているのでしょうか?
宣言はまったく同じです。 auto
は(ほぼ)template type deductionと同じです。星を明示的に置くと、コードが少し読みやすくなり、プログラマはbar2
がポインタであることを認識させます。
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アクセスのみが必要です。
std::vector<X*> v = /* ... */;
for (const auto * p : v)
{
observe(p->foo()); // no need for a mutable *p
}
両方bar1
とbar2
が同じである。この具体例では:ちょうどauto *
は、我々が明示的const
を言うことによって避けることができる可変へのポインタを、推測するでしょう。私は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;
}
auto *
"文書の意思" を使用。そしてauto *p = expr;
は、expr
がポインタを返す場合にのみ、正しく導き出すことができます。例:
int f();
auto q = f(); // OK
auto *p = f(); // error: unable to deduce 'auto*' from 'f()'
ポインタのない控除を禁止することについての良い点、upvoted。 – vsoftco
はい、次の演算子&はnotnullまたはconstを伝播するスマートポインタを返すようにオーバーロードされ、auto *が実行されます。 –
他にも同じコードが生成されます。アスタリスクはラインノイズです(例えば、&foo
がget_foo()
に置き換えられた場合、生ポインタからスマートポインタへの切り替えが難しくなります)。明示的にしたい場合は、是非、明示してください。型推論を使用しているときは、コンパイラにその作業を任せてください。アスタリスクの欠如は、オブジェクトがポインタではないことを意味するものではありません。
カッコ内のコメントはもっと重視する価値があると思います。他の人が与えている簡単な例でも、 '*'を追加するとコードを読みやすくすることができますが、メンテナンスが難しくなります。私は個人的には、「自動」の主な利点は、タイピングを減らすか読みやすさを向上させるよりもメンテナンスを容易にすることだと感じています。 – ToddR
あなたはconst
修飾子を使用する場合には大きな違いがあります: `MyFn`戻り値の型が` int`、 `自動* pを= FNあるとして
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
を(X、-X)'(コンパイルされません'*'のおかげで、そうでなければエラーのために 'p-> Create()'を待つべきです):-)。 – Jarod42
@ Jarod42:はい、私はあまりにも少数の異なるエンティティを使用していました。一定。 –