C ++のポインター変数と参照変数の違いは何ですか?

3386
prakash 2008-09-12 10:03.

参照はシンタックスシュガーであることを知っているので、コードは読み書きが簡単です。

しかし、違いは何ですか?

30 answers

1803
Brian R. Bondy 2008-09-12 10:08.
  1. ポインタを再割り当てできます。

    int x = 5;
    int y = 6;
    int *p;
    p = &x;
    p = &y;
    *p = 10;
    assert(x == 5);
    assert(y == 10);
    

    参照はできません。初期化時に割り当てる必要があります。

    int x = 5;
    int y = 6;
    int &r = x;
    
  2. ポインタはスタック上に独自のメモリアドレスとサイズ(x86では4バイト)を持っていますが、参照は(元の変数と)同じメモリアドレスを共有しますが、スタック上でいくらかのスペースを占有します。参照は元の変数自体と同じアドレスを持っているため、参照を同じ変数の別の名前と考えるのが安全です。注:ポインターが指すものは、スタックまたはヒープ上にある可能性があります。参照と同じです。このステートメントでの私の主張は、ポインターがスタックを指している必要があるということではありません。ポインタは、メモリアドレスを保持する単なる変数です。この変数はスタック上にあります。参照にはスタック上に独自のスペースがあり、アドレスは参照する変数と同じであるためです。スタックとヒープの詳細。これは、コンパイラが通知しない参照の実際のアドレスがあることを意味します。

    int x = 0;
    int &r = x;
    int *p = &x;
    int *p2 = &r;
    assert(p == p2);
    
  3. 追加レベルの間接参照を提供するポインターへのポインターへのポインターを持つことができます。一方、参照は1レベルの間接参照しか提供しません。

    int x = 0;
    int y = 0;
    int *p = &x;
    int *q = &y;
    int **pp = &p;
    pp = &q;//*pp = q
    **pp = 4;
    assert(y == 4);
    assert(x == 0);
    
  4. ポインタはnullptr直接割り当てることができますが、参照はできません。十分に努力し、その方法を知っている場合は、参照のアドレスを作成できますnullptr。同様に、十分に努力すれば、ポインタへの参照を持つことができ、その参照にはnullptr。を含めることができます。

    int *p = nullptr;
    int &r = nullptr; <--- compiling error
    int &r = *p;  <--- likely no compiling error, especially if the nullptr is hidden behind a function call, yet it refers to a non-existent int at address 0
    
  5. ポインターは配列を反復処理できます。++ポインタが指している次の項目+ 4に移動したり、5番目の要素に移動したりするために使用できます。これは、ポインタが指すオブジェクトのサイズに関係ありません。

  6. ポインタは、ポインタが指す*メモリ位置にアクセスするために逆参照する必要がありますが、参照は直接使用できます。クラス/構造体へのポインタはその->メンバーにアクセスするために使用しますが、参照はを使用し.ます。

  7. 参照を配列に詰め込むことはできませんが、ポインターを詰め込むことはできます(ユーザー@litbが言及)

  8. const参照は、一時参照にバインドできます。ポインタはできません(間接参照なしではありません):

    const int &x = int(12); //legal C++
    int *y = &int(12); //illegal to dereference a temporary.
    

    これによりconst&、引数リストなどでの使用がより安全になります。

415
Christoph 2009-02-28 11:26.

C ++リファレンスとは(Cプログラマー向け

リファレンスはと考えることができ、一定のポインタコンパイラが適用される自動間接付き(一定の値へのポインタと混同しないように!)、すなわち*あなたのための演算子を。

すべての参照はnull以外の値で初期化する必要があります。そうしないと、コンパイルが失敗します。参照のアドレスを取得することはできません-アドレス演算子は代わりに参照された値のアドレスを返します-また、参照に対して算術演算を行うこともできません。

Cプログラマーは、間接参照が発生した場合、または引数が関数のシグネチャを見ずに値またはポインターによって渡された場合に明確でなくなるため、C ++参照を嫌う可能性があります。

C ++プログラマーは、ポインターが安全でないと見なされるため、ポインターの使用を嫌う可能性があります-参照は、最も些細な場合を除いて、定数ポインターよりも実際には安全ではありませんが-自動間接参照の利便性に欠け、異なるセマンティックな意味合いを持っています。

C ++ FAQの次のステートメントを検討してください

参照は、基になるアセンブリ言語のアドレスを使用して実装されることがよくありますが、参照をオブジェクトへの変な見た目のポインタと考えないでください。参照オブジェクトです。これは、オブジェクトへのポインタでも、オブジェクトのコピーでもありません。これは、あるオブジェクト。

しかし、参照が本当にオブジェクトである場合、どのようにしてぶら下がっている参照があるのでしょうか?管理されていない言語では、参照をポインタよりも「安全」にすることは不可能です。一般に、スコープの境界を越えて値を確実にエイリアスする方法はありません。

C ++参照が役立つと考える理由

Cの背景から来ると、C ++参照はややばかげた概念のように見えるかもしれませんが、可能な場合はポインターの代わりにそれらを使用する必要があります。自動間接参照便利であり、参照はRAIIを処理するときに特に役立ちますが、安全性が認識されているためではありません。利点ではなく、慣用的なコードの記述が煩わしくないためです。

RAIIはC ++の中心的な概念の1つですが、コピーのセマンティクスと自明ではありません。参照によってオブジェクトを渡すと、コピーが含まれないため、これらの問題が回避されます。言語に参照が存在しない場合は、代わりにポインターを使用する必要があります。これは使用が面倒であるため、ベストプラクティスソリューションは代替ソリューションよりも簡単であるという言語設計の原則に違反します。

201
Matt Price 2008-09-12 11:43.

本当に衒学者になりたいのであれば、ポインタではできない参照でできることが1つあります。それは、一時オブジェクトの存続期間を延長することです。C ++では、const参照を一時オブジェクトにバインドすると、そのオブジェクトの有効期間が参照の有効期間になります。

std::string s1 = "123";
std::string s2 = "456";

std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;

この例では、s3_copyは、連結の結果である一時オブジェクトをコピーします。一方、本質的にs3_referenceは一時オブジェクトになります。これは実際には、参照と同じ有効期間を持つ一時オブジェクトへの参照です。

constそれなしでこれを試してみると、コンパイルに失敗するはずです。非const参照を一時オブジェクトにバインドすることはできません。また、そのアドレスを取得することもできません。

141
Noname 2008-09-12 10:07.

シンタックスシュガーとは別に、参照はconstポインターです(へのポインターではありませんconst)。参照変数を宣言するときに参照先を確立する必要があり、後で変更することはできません。

更新:もう少し考えてみると、重要な違いがあります。

constポインターのターゲットは、そのアドレスを取得してconstキャストを使用することで置き換えることができます。

参照のターゲットは、UB以外の方法で置き換えることはできません。

これにより、コンパイラーは参照に対してさらに最適化を行うことができます。

130
Mark Ransom 2008-09-12 11:06.

世論に反して、NULLの参照を持つ可能性があります。

int * p = NULL;
int & r = *p;
r = 1;  // crash! (if you're lucky)

確かに、参照を使用するのははるかに困難ですが、それを管理すると、それを見つけようとして髪を引き裂くでしょう。参照はC ++では本質的に安全ではありません

技術的には、これは無効な参照であり、null参照ではありません。C ++は、他の言語で見られるような概念としてnull参照をサポートしていません。他の種類の無効な参照もあります。任意の無効な参照はの亡霊上げる未定義の動作を単に無効なポインタを使用してしまうと、。

実際のエラーは、参照に割り当てる前のNULLポインターの逆参照にあります。しかし、私はその条件でエラーを生成するコンパイラーを知りません-エラーはコードのさらに進んだポイントに伝播します。それがこの問題をとても陰湿なものにしているのです。ほとんどの場合、NULLポインターを逆参照すると、その場所でクラッシュし、それを理解するのに多くのデバッグは必要ありません。

上記の私の例は短く、不自然です。これがより現実的な例です。

class MyClass
{
    ...
    virtual void DoSomething(int,int,int,int,int);
};

void Foo(const MyClass & bar)
{
    ...
    bar.DoSomething(i1,i2,i3,i4,i5);  // crash occurs here due to memory access violation - obvious why?
}

MyClass * GetInstance()
{
    if (somecondition)
        return NULL;
    ...
}

MyClass * p = GetInstance();
Foo(*p);

繰り返しますが、null参照を取得する唯一の方法は、不正な形式のコードを使用することであり、一度取得すると、未定義の動作が発生します。null参照をチェックすることは決して意味がありません。たとえばif(&bar==NULL)...、試すことはできますが、コンパイラがステートメントを最適化して存在しない可能性があります。有効な参照がNULLになることは決してないため、コンパイラの観点からは、比較は常にfalseでありif、デッドコードとして句を自由に削除できます。これが未定義の動作の本質です。

問題を回避する適切な方法は、参照を作成するためにNULLポインターを逆参照しないようにすることです。これを実現するための自動化された方法は次のとおりです。

template<typename T>
T& deref(T* p)
{
    if (p == NULL)
        throw std::invalid_argument(std::string("NULL reference"));
    return *p;
}

MyClass * p = GetInstance();
Foo(deref(p));

より優れたライティングスキルを持つ人からのこの問題の古い見方については、JimHyslopとHerbSutterのNullReferencesを参照してください。

nullポインターを逆参照する危険性の別の例については、RaymondChenがコードを別のプラットフォームに移植しようとしたときに未定義の動作を公開するを参照してください。

120
Orion Edwards 2008-09-12 12:10.

あなたは最も重要な部分を忘れました:

ポインタを使用した->
member-accessは、参照を使用したmember-accessを使用します。.

foo.barある明確に優れてfoo->barいることと同じ方法で、VIがあり、明らかに優れてEmacsの:-)

76
Cort Ammon 2013-09-01 17:44.

参照はポインターと非常に似ていますが、コンパイラーの最適化に役立つように特別に作成されています。

  • 参照は、コンパイラがどの参照エイリアスをどの変数で追跡するのが実質的に簡単になるように設計されています。2つの主要な機能が非常に重要です。「参照演算」と参照の再割り当てがありません。これらにより、コンパイラーは、コンパイル時にどの参照がどの変数をエイリアスするかを把握できます。
  • 参照は、コンパイラがレジスタに入れることを選択した変数など、メモリアドレスを持たない変数を参照できます。ローカル変数のアドレスを取得する場合、コンパイラがそれをレジスタに入れるのは非常に困難です。

例として:

void maybeModify(int& x); // may modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // This function is designed to do something particularly troublesome
    // for optimizers. It will constantly call maybeModify on array[0] while
    // adding array[1] to array[2]..array[size-1]. There's no real reason to
    // do this, other than to demonstrate the power of references.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(array[0]);
        array[i] += array[1];
    }
}

最適化コンパイラは、a [0]とa [1]にかなりの数のアクセスをしていることに気付くかもしれません。アルゴリズムを次のように最適化することをお勧めします。

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Do the same thing as above, but instead of accessing array[1]
    // all the time, access it once and store the result in a register,
    // which is much faster to do arithmetic with.
    register int a0 = a[0];
    register int a1 = a[1]; // access a[1] once
    for (int i = 2; i < (int)size; i++) {
        maybeModify(a0); // Give maybeModify a reference to a register
        array[i] += a1;  // Use the saved register value over and over
    }
    a[0] = a0; // Store the modified a[0] back into the array
}

このような最適化を行うには、呼び出し中にarray [1]を変更できないことを証明する必要があります。これはかなり簡単です。iが2以上になることはないため、array [i]がarray [1]を参照することはできません。多分Modify()は参照としてa0を与えられます(array [0]のエイリアス)。「参照」演算がないため、コンパイラは、maybeModifyがxのアドレスを取得しないことを証明する必要があり、array [1]を変更するものがないことを証明しました。

また、a0に一時的なレジスタコピーがある間は、将来の呼び出しでa [0]を読み書きできる方法がないことを証明する必要があります。多くの場合、参照がクラスインスタンスのような永続的な構造に格納されないことは明らかであるため、これを証明するのは簡単です。

今度はポインタで同じことをします

void maybeModify(int* x); // May modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Same operation, only now with pointers, making the
    // optimization trickier.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(&(array[0]));
        array[i] += array[1];
    }
}

動作は同じです。すでにポインタを指定しているため、maybeModifyがarray [1]を変更しないことを証明するのは今でははるかに困難です。猫は袋から出ています。ここで、はるかに難しい証明を行う必要があります。maybeModifyの静的分析により、&x + 1に書き込まれないことを証明します。また、array [0]を参照できるポインターを決して保存しないことも証明する必要があります。トリッキーなように。

最近のコンパイラーは静的分析でますます良くなっていますが、それらを助けて参照を使用することは常に素晴らしいことです。

もちろん、そのような巧妙な最適化を除けば、コンパイラーは必要に応じて参照をポインターに変換します。

編集:この回答を投稿してから5年後、同じアドレス指定の概念を見る方法が異なるだけでなく、参照が異なるという実際の技術的な違いを見つけました。参照は、ポインタでは不可能な方法で一時オブジェクトの寿命を変更できます。

F createF(int argument);

void extending()
{
    const F& ref = createF(5);
    std::cout << ref.getArgument() << std::endl;
};

通常、toの呼び出しによって作成されたオブジェクトなどの一時的なオブジェクトcreateF(5)は、式の最後で破棄されます。ただし、そのオブジェクトを参照にバインドすることによりref、C ++はref、スコープ外になるまでその一時オブジェクトの寿命を延ばします。

70
Vincent Robert 2008-09-20 02:23.

実際、参照は実際にはポインタのようなものではありません。

コンパイラは変数への「参照」を保持し、名前をメモリアドレスに関連付けます。コンパイル時に変数名をメモリアドレスに変換するのがその仕事です。

参照を作成するときは、ポインター変数に別の名前を割り当てることだけをコンパイラーに伝えます。そのため、参照は「nullを指す」ことができません。これは、変数が「nullを指す」ことも、そうでないこともできるためです。

ポインタは変数です。他の変数のアドレスが含まれているか、nullの場合があります。重要なことは、ポインターには値があり、参照にはそれが参照している変数しかないということです。

次に、実際のコードについて説明します。

int a = 0;
int& b = a;

ここでは、a;を指す別の変数を作成していません。の値を保持するメモリコンテンツに別の名前を追加しているだけですa。このメモリには2つの名前とがaありb、どちらの名前でもアドレス指定できます。

void increment(int& n)
{
    n = n + 1;
}

int a;
increment(a);

関数を呼び出すとき、コンパイラは通常、コピー先の引数用のメモリスペースを生成します。関数シグネチャは、作成する必要のあるスペースを定義し、これらのスペースに使用する必要のある名前を指定します。パラメータを参照として宣言すると、メソッド呼び出し中に新しいメモリスペースを割り当てる代わりに、入力変数のメモリスペースを使用するようにコンパイラに指示するだけです。関数が呼び出し元のスコープで宣言された変数を直接操作すると言うのは奇妙に思えるかもしれませんが、コンパイルされたコードを実行すると、スコープがなくなることに注意してください。単なるフラットメモリがあり、関数コードは任意の変数を操作できます。

これで、extern変数を使用する場合など、コンパイル時にコンパイラが参照を認識できない場合があります。したがって、参照は、基になるコードのポインターとして実装される場合とされない場合があります。しかし、私があなたに与えた例では、それはおそらくポインターで実装されないでしょう。

45
Noname 2008-09-12 10:12.

参照をすることはできませんNULL

34
Kunal Vyas 2011-05-21 09:26.

参照とポインターの両方が別の値に間接的にアクセスするために使用されますが、参照とポインターの間には2つの重要な違いがあります。1つ目は、参照が常にオブジェクトを参照していることです。参照を初期化せずに定義するとエラーになります。割り当ての動作は、2番目の重要な違いです。参照に割り当てると、参照がバインドされているオブジェクトが変更されます。別のオブジェクトへの参照を再バインドしません。初期化されると、参照は常に同じ基になるオブジェクトを参照します。

これらの2つのプログラムフラグメントについて考えてみます。最初に、あるポインタを別のポインタに割り当てます。

int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2;    // pi now points to ival2

代入、ivalの後、piによってアドレス指定されたオブジェクトは変更されません。割り当てにより、piの値が変更され、別のオブジェクトを指すようになります。次に、2つの参照を割り当てる同様のプログラムについて考えてみます。

int &ri = ival, &ri2 = ival2;
ri = ri2;    // assigns ival2 to ival

この割り当ては、参照自体ではなく、riによって参照される値であるivalを変更します。割り当て後も、2つの参照は元のオブジェクトを参照し、それらのオブジェクトの値も同じになります。

33
Lightness Races in Orbit 2014-10-30 07:17.

抽象的または学術的な方法でコンピュータ言語を勉強することに慣れていない場合、意味論的な違いが難解に見えるかもしれません。

最高レベルでは、参照の概念は、それらが透過的な「エイリアス」であるということです。コンピュータはアドレスを使用してそれらを機能させることができますが、それについて心配する必要はありません。既存のオブジェクトの「単なる別の名前」と見なす必要があり、構文はそれを反映しています。これらはポインターよりも厳密であるため、ダングリングポインターを作成しようとしているときよりも、ダングリング参照を作成しようとしているときにコンパイラーがより確実に警告することができます。

それを超えて、もちろん、ポインタと参照の間にはいくつかの実際的な違いがあります。それらを使用するための構文は明らかに異なり、参照を「再シート」したり、何もないことへの参照を持ったり、参照へのポインターを持ったりすることはできません。

27
fatma.ekici 2013-01-02 07:45.

参照は別の変数のエイリアスですが、ポインタは変数のメモリアドレスを保持します。渡されるオブジェクトがコピーではなくオブジェクト自体になるように、参照は通常、関数パラメーターとして使用されます。

    void fun(int &a, int &b); // A common usage of references.
    int a = 0;
    int &b = a; // b is an alias for a. Not so common to use. 
20
MSN 2008-09-13 13:27.

占有するスペースの副作用を(コードを実行せずに)実際に確認することはできないため、占有するスペースの量は関係ありません。

一方、参照とポインターの大きな違いの1つは、const参照に割り当てられた一時的なものは、const参照がスコープ外になるまで存続することです。

例えば:

class scope_test
{
public:
    ~scope_test() { printf("scope_test done!\n"); }
};

...

{
    const scope_test &test= scope_test();
    printf("in scope\n");
}

印刷されます:

in scope
scope_test done!

これは、ScopeGuardが機能することを可能にする言語メカニズムです。

20
Life 2014-01-14 03:14.

これはチュートリアルに基づいています。書かれていることはそれをより明確にします:

>>> The address that locates a variable within memory is
    what we call a reference to that variable. (5th paragraph at page 63)

>>> The variable that stores the reference to another
    variable is what we call a pointer. (3rd paragraph at page 64)

覚えておくと、

>>> reference stands for memory location
>>> pointer is a reference container (Maybe because we will use it for
several times, it is better to remember that reference.)

さらに、ほとんどすべてのポインターチュートリアルを参照できるため、ポインターは、ポインターを配列に類似させるポインター演算によってサポートされるオブジェクトです。

次のステートメントを見てください。

int Tom(0);
int & alias_Tom = Tom;

alias_Tomalias of a variable(とは異なりtypedef、はalias of a type)として理解できますTom。このようなステートメントの用語は、の参照を作成することであることを忘れてもかまいませんTom

20
tanweer alam 2013-02-26 19:20.

参照は、一部のメモリに付けられた別の名前ではありません。これは、使用時に自動的に参照解除される不変のポインターです。基本的にそれは要約すると:

int& j = i;

内部的には

int* const j = &i;
18
FrankHB 2019-02-17 21:37.

直接の答え

C ++のリファレンスとは何ですか?オブジェクトタイプはないタイプの特定のインスタンス。

C ++のポインタとは何ですか?オブジェクト型である型の特定のインスタンス。

オブジェクト型のISO C ++の定義:

オブジェクトタイプは、(おそらくあるCVは-qualified)関数型ではなく、参照型でないタイプではなく、CVのボイド。

オブジェクトタイプはC ++のタイプユニバースのトップレベルのカテゴリであることを知っておくことが重要かもしれません。参照もトップレベルのカテゴリです。しかし、ポインタはそうではありません。

ポインタと参照は、複合タイプのコンテキストで一緒に言及されています。これは基本的に、参照がないCから継承された(および拡張された)宣言子構文の性質によるものです。(さらに、C ++ 11以降、複数の種類の参照宣言子がありますが、ポインターはまだ「ユニタイプ」です:&+ &&vs. *)したがって、このコンテキストで同様のスタイルのCを使用して、「拡張」によって固有の言語をドラフトすることはある程度合理的です。 。(宣言子の構文は構文の表現力を大幅に浪費し、人間のユーザーと実装の両方を苛立たせます。したがって、それらすべてが新しい言語設計に組み込まれる資格があるわけではありません。これはまったく異なるトピックです。ただし、PL設計について。)

それ以外の場合、ポインタを参照とともに特定の種類の型として修飾できることは重要ではありません。構文の類似性以外に共有する共通のプロパティが少なすぎるため、ほとんどの場合、それらをまとめる必要はありません。

上記のステートメントは、タイプとして「ポインタ」と「参照」のみに言及していることに注意してください。それらのインスタンス(変数など)についていくつかの興味深い質問があります。誤解も多すぎます。

トップレベルのカテゴリの違いは、ポインタに直接結び付けられていない多くの具体的な違いをすでに明らかにしている可能性があります。

  • オブジェクトタイプは、最上位のcv修飾子を持つことができます。参照はできません。
  • オブジェクトタイプの変数は、抽象マシンのセマンティクスに従ってストレージを占有します。参照はストレージを占有する必要はありません(詳細については、以下の誤解に関するセクションを参照してください)。
  • ..。

参照に関するいくつかの特別なルール:

  • 複合宣言子は、参照に対してより制限があります。
  • 参照は折りたたまれる可能性があります。
    • &&テンプレートパラメータの推定中に折りたたまれた参照に基づくパラメータに関する特別なルール(「転送参照」として)により、パラメータの「完全な転送」が可能になります。
  • 参照には、初期化に特別な規則があります。参照型として宣言された変数の有効期間は、拡張によって通常のオブジェクトとは異なる場合があります。
    • ところで、初期化のような他のいくつかのコンテキストstd::initializer_listは、参照の有効期間延長のいくつかの同様のルールに従います。ワームのもう1つの缶です。
  • ..。

誤解

シンタックスシュガー

参照はシンタックスシュガーであることを知っているので、コードは読み書きが簡単です。

技術的には、これは明らかに間違っています。参照は、セマンティックの違いなしに他の機能に正確に置き換えることができないため、C ++の他の機能の構文糖衣構文ではありません。

(同様に、ラムダ式のSはない、それは正確ような「未指定」のプロパティでシミュレートすることができないので、C ++の任意の他の特徴の糖衣構文捕捉変数の宣言順序このような変数の初期化順序ができるため重要であり得ます、重要です。)

C ++には、この厳密な意味で数種類の構文糖衣しかありません。1つのインスタンスは(Cから継承された)組み込み(オーバーロードされていない)演算子です[]。これは、組み込み演算子の単項*およびバイナリに対して、特定の形式の組み合わせとまったく同じセマンティックプロパティを持つように定義されてい+ます。

ストレージ

したがって、ポインタと参照はどちらも同じ量のメモリを使用します。

上記のステートメントは単に間違っています。このような誤解を避けるために、代わりにISO C ++ルールを見てください。

[intro.object] / 1:

...オブジェクトは、その構築期間中、その存続期間中、およびその破壊期間中、ストレージの領域を占有します。..。

[dcl.ref] / 4:

参照にストレージが必要かどうかは指定されていません。

これらはセマンティックプロパティであることに注意してください。

語用論

言語設計の意味でポインタを参照と組み合わせるのに十分な資格がない場合でも、パラメータタイプを選択する場合など、他のコンテキストでポインタを選択することについて議論の余地がある議論があります。

しかし、これがすべてではありません。つまり、ポインタと参照よりも考慮しなければならないことがたくさんあります。

このような過度に具体的な選択に固執する必要がない場合、ほとんどの場合、答えは短いですポインタを使用する必要がないので、使用しません。ポインタは通常、予期しないことが多すぎることを意味し、コードの保守性と(さらには)移植性を損なう暗黙の仮定に依存するため、十分に悪いものです。ポインタに不必要に依存することは間違いなく悪いスタイルであり、現代のC ++の意味では避ける必要があります。目的を再考すると、ほとんどの場合、ポインタが最後の種類の機能であることが最終的にわかります。

  • 言語ルールでは、特定のタイプを明示的に使用する必要がある場合があります。これらの機能を使用する場合は、ルールに従ってください。
    • コピーコンストラクタは、特定のタイプの必要CV -&第一引数の型として参照型を。(そして通常それはconst修飾されるべきです。)
    • 移動コンストラクタは、特定のタイプの必要CV -&&第一引数の型として参照型を。(通常、修飾子はありません。)
    • 演算子の特定のオーバーロードには、参照型または非参照型が必要です。例えば:
      • operator=特別なメンバー関数としてオーバーロードされるには、コピー/移動コンストラクターの1番目のパラメーターと同様の参照型が必要です。
      • 接尾辞に++はダミーが必要intです。
      • ..。
  • 値渡し(つまり、非参照型を使用)で十分であることがわかっている場合は、特にC ++ 17で必須のコピーの省略をサポートする実装を使用する場合は、直接使用してください。(警告:ただし、必要性について徹底的に推論することは非常に複雑になる可能性があります。)
  • 所有権を持っていくつかのハンドルを操作したい場合は、生のポインターではなく、unique_ptrandのようなスマートポインターを使用しますshared_ptr(または、不透明にする必要がある場合は、自作のポインターを使用します)。
  • ある範囲でいくつかの反復を行う場合は、生のポインターが非常に具体的に(たとえば、ヘッダーの依存関係が少ないために)うまくいくと確信していない限り、生のポインターではなく、イテレーター(または標準ライブラリによってまだ提供されていないいくつかの範囲)を使用しますケース。
  • 値渡しで十分であり、明示的なnull許容セマンティクスが必要なstd::optional場合は、生のポインターではなく、のようなラッパーを使用してください。
  • 上記の理由で値渡しが理想的ではないことがわかっていて、null許容のセマンティクスが必要ない場合は、{左辺値、右辺値、転送}参照を使用してください。
  • 従来のポインタのようなセマンティクスが必要な場合でもobserver_ptr、Library FundamentalTSのようにもっと適切なものがあることがよくあります。

唯一の例外は、現在の言語では回避できません。

  • 上記のスマートポインターを実装する場合、生のポインターを処理する必要がある場合があります。
  • 特定の言語相互運用ルーチンには、のようなポインターが必要ですoperator new。(ただし、CVは-void*あなたは上のいくつかの非準拠の拡張に依存している場合を除き、それは予期しないポインタ算術演算を除外するので、通常のオブジェクトポインタに比べてまだかなり違うと安全ですvoid*GNUのように。)
  • 関数ポインターはキャプチャなしでラムダ式から変換できますが、関数参照は変換できません。このような場合は、意図的にnull許容値が必要ない場合でも、非ジェネリックコードで関数ポインターを使用する必要があります。

したがって、実際には、答えは非常に明白です。疑わしい場合は、ポインタを避けてください。ポインタを使用する必要があるのは、他に適切なものがないという非常に明確な理由がある場合のみです。上記のいくつかの例外的なケースを除いて、そのような選択はほとんどの場合、純粋にC ++固有ではありません(ただし、言語実装固有である可能性があります)。そのようなインスタンスは次のようになります。

  • 古いスタイル(C)のAPIを提供する必要があります。
  • 特定のC ++実装のABI要件を満たす必要があります。
  • 特定の実装の前提に基づいて、実行時にさまざまな言語実装(さまざまなアセンブリ、言語ランタイム、および一部の高レベルクライアント言語のFFIを含む)と相互運用する必要があります。
  • 極端な場合には、翻訳(コンパイルとリンク)の効率を改善する必要があります。
  • 極端な場合には、シンボルの膨張を回避する必要があります。

言語の中立性に関する警告

Googleの検索結果(C ++に固有ではない)で質問が表示された場合、これは間違った場所である可能性が非常に高くなります。

C ++での参照は、本質的にファーストクラスではないため、非常に「奇妙」です。参照されるオブジェクトまたは関数として扱われるため、の左オペランドなど、一部のファーストクラスの操作をサポートする機会がありません。参照されるオブジェクトのタイプに依存しないメンバーアクセス演算子。他の言語では、参照に同様の制限がある場合とない場合があります。

C ++での参照は、異なる言語間で意味を保持しない可能性があります。たとえば、参照は一般にC ++のように値にnull以外のプロパティを意味しないため、そのような仮定は他の言語では機能しない可能性があります(Java、C#などの反例は非常に簡単に見つかります)。

一般に、さまざまなプログラミング言語の参照にはまだいくつかの共通のプロパティが存在する可能性がありますが、SOの他のいくつかの質問のために残しておきましょう。

(補足:この質問は、ALGOL68とPL / Iのように、「Cのような」言語が関係するよりも早く重要になる可能性があります。)

17
Destructor 2015-02-10 03:17.

ポインタへの参照はC ++で可能ですが、その逆は不可能です。つまり、参照へのポインタは不可能です。ポインターへの参照は、ポインターを変更するためのよりクリーンな構文を提供します。この例を見てください:

#include<iostream>
using namespace std;

void swap(char * &str1, char * &str2)
{
  char *temp = str1;
  str1 = str2;
  str2 = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap(str1, str2);
  cout<<"str1 is "<<str1<<endl;
  cout<<"str2 is "<<str2<<endl;
  return 0;
}

そして、上記のプログラムのCバージョンを検討してください。Cでは、ポインタからポインタ(複数の間接参照)を使用する必要があり、混乱を招き、プログラムが複雑に見える場合があります。

#include<stdio.h>
/* Swaps strings by swapping pointers */
void swap1(char **str1_ptr, char **str2_ptr)
{
  char *temp = *str1_ptr;
  *str1_ptr = *str2_ptr;
  *str2_ptr = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap1(&str1, &str2);
  printf("str1 is %s, str2 is %s", str1, str2);
  return 0;
}

ポインタへの参照の詳細については、以下にアクセスしてください。

  • C ++:ポインタへの参照
  • Pointer-to-PointerおよびReference-to-Pointer。

私が言ったように、参照へのポインタは不可能です。次のプログラムを試してください。

#include <iostream>
using namespace std;

int main()
{
   int x = 10;
   int *ptr = &x;
   int &*ptr1 = ptr;
}
16
Aardvark 2008-09-13 03:41.

これらのいずれかが必要でない限り、参照を使用します。

  • ヌルポインタは番兵値として使用できます。多くの場合、関数のオーバーロードやブール値の使用を回避するための安価な方法です。

  • ポインタで算術演算を行うことができます。例えば、p += offset;

15
Andrzej 2012-02-06 22:59.

ポインタと参照の間には、誰も言及していない基本的な違いが1つあります。参照は、関数の引数で参照渡しのセマンティクスを有効にします。ポインタは、最初は表示されませんが、表示されません。値渡しのセマンティクスのみを提供します。これは、この記事で非常にうまく説明されています。

よろしく、&rzej

14
Tory 2014-10-15 11:38.

混乱を招くリスクがありますが、いくつかの入力を投入したいと思います。コンパイラが参照を実装する方法に大きく依存すると確信していますが、gccの場合、参照はスタック上の変数のみを指すことができるという考えです。実際には正しくありません。たとえば、次のようにします。

#include <iostream>
int main(int argc, char** argv) {
    // Create a string on the heap
    std::string *str_ptr = new std::string("THIS IS A STRING");
    // Dereference the string on the heap, and assign it to the reference
    std::string &str_ref = *str_ptr;
    // Not even a compiler warning! At least with gcc
    // Now lets try to print it's value!
    std::cout << str_ref << std::endl;
    // It works! Now lets print and compare actual memory addresses
    std::cout << str_ptr << " : " << &str_ref << std::endl;
    // Exactly the same, now remember to free the memory on the heap
    delete str_ptr;
}

これを出力します:

THIS IS A STRING
0xbb2070 : 0xbb2070

メモリアドレスもまったく同じであることに気付いた場合は、参照がヒープ上の変数を正常に指していることを意味します。今、あなたが本当に気紛れになりたいのなら、これもうまくいきます:

int main(int argc, char** argv) {
    // In the actual new declaration let immediately de-reference and assign it to the reference
    std::string &str_ref = *(new std::string("THIS IS A STRING"));
    // Once again, it works! (at least in gcc)
    std::cout << str_ref;
    // Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
    delete &str_ref;
    /*And, it works, because we are taking the memory address that the reference is
    storing, and deleting it, which is all a pointer is doing, just we have to specify
    the address with '&' whereas a pointer does that implicitly, this is sort of like
    calling delete &(*str_ptr); (which also compiles and runs fine).*/
}

これを出力します:

THIS IS A STRING

したがって、参照は内部のポインタであり、どちらもメモリアドレスを格納しているだけであり、アドレスが指している場所は関係ありません。std:: cout << str_ref;を呼び出した場合はどうなると思いますか。delete&str_refを呼び出した後?まあ、明らかにそれはうまくコンパイルされますが、それはもはや有効な変数を指していないので実行時にセグメンテーション違反を引き起こします、私たちは本質的に壊れた参照を持っています(それがスコープから外れるまで)が役に立たないです。

言い換えれば、参照は、ポインタの仕組みが抽象化されたポインタに他ならず、より安全で使いやすくなっています(偶発的なポインタの計算、「。」と「->」の混同などはありません)。上記の私の例のようなナンセンスを試さないでください;)

今すぐにかかわらず、コンパイラハンドルの参照は、それがする方法の常に参照するので、フードの下ポインタのいくつかの種類を持っている必要があります期待通りの仕事にそれのために特定のメモリアドレスに特定の変数を参照してください、何ので、(この歩き回るはありません用語「参照」)。

参照で覚えておくことが重要な唯一の主要なルールは、宣言時に定義する必要があるということです(ヘッダー内の参照を除いて、その場合、含まれているオブジェクトの後にコンストラクターで定義する必要があります。構築するには遅すぎます)。

上記の私の例は、参照が何であるかを示す例であり、そのような方法で参照を使用したくないことを覚えておいてください!参照を適切に使用するために、ここにはすでに頭に釘を打った答えがたくさんあります

14
kriss 2010-01-30 05:15.

もう1つの違いは、void型へのポインター(およびそれは何かへのポインターを意味します)を持つことができますが、voidへの参照は禁止されていることです。

int a;
void * p = &a; // ok
void & p = a;  //  forbidden

この特定の違いに本当に満足しているとは言えません。私は、アドレスを持つものへの参照という意味で許可され、それ以外の場合は参照に対して同じ動作が許可されることを強く望んでいます。これにより、参照を使用してmemcpyなどのCライブラリ関数に相当するものを定義できます。

13
Adisak 2009-10-15 15:57.

また、インライン化された関数へのパラメーターである参照は、ポインターとは異なる方法で処理される場合があります。

void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
    int testptr=0;
    increment(&testptr);
}
void increftest()
{
    int testref=0;
    increment(testref);
}

多くのコンパイラは、ポインタバージョン1をインライン化するときに、実際にはメモリへの書き込みを強制します(アドレスを明示的に取得しています)。ただし、より最適なレジスタにリファレンスを残します。

もちろん、インライン化されていない関数の場合、ポインターと参照は同じコードを生成します。関数によって変更されて返されない場合は、参照よりも値で組み込み関数を渡す方が常に適切です。

11
Don Wakefield 2008-09-13 07:59.

参照のもう1つの興味深い使用法は、ユーザー定義型のデフォルト引数を提供することです。

class UDT
{
public:
   UDT() : val_d(33) {};
   UDT(int val) : val_d(val) {};
   virtual ~UDT() {};
private:
   int val_d;
};

class UDT_Derived : public UDT
{
public:
   UDT_Derived() : UDT() {};
   virtual ~UDT_Derived() {};
};

class Behavior
{
public:
   Behavior(
      const UDT &udt = UDT()
   )  {};
};

int main()
{
   Behavior b; // take default

   UDT u(88);
   Behavior c(u);

   UDT_Derived ud;
   Behavior d(ud);

   return 1;
}

デフォルトのフレーバーは、参照の「一時的な」側面への「bindconst参照」を使用します。

11
Arlene Batada 2013-03-15 17:03.

このプログラムは、質問の答えを理解するのに役立つかもしれません。これは、参照「j」と変数「x」を指すポインタ「ptr」の単純なプログラムです。

#include<iostream>

using namespace std;

int main()
{
int *ptr=0, x=9; // pointer and variable declaration
ptr=&x; // pointer to variable "x"
int & j=x; // reference declaration; reference to variable "x"

cout << "x=" << x << endl;

cout << "&x=" << &x << endl;

cout << "j=" << j << endl;

cout << "&j=" << &j << endl;

cout << "*ptr=" << *ptr << endl;

cout << "ptr=" << ptr << endl;

cout << "&ptr=" << &ptr << endl;
    getch();
}

プログラムを実行し、出力を見ると理解できます。

また、10分を空けて、このビデオを見てください。 https://www.youtube.com/watch?v=rlJrrGV0iOg

11
Ap31 2017-07-07 09:48.

ここで取り上げていない点がもう一つあるような気がします。

ポインタとは異なり、参照は参照するオブジェクトと構文的に同等です。つまり、オブジェクトに適用できる操作はすべて参照に対して機能し、まったく同じ構文で機能します(例外はもちろん初期化です)。

これは表面的なように見えるかもしれませんが、このプロパティは、次のような多くのC ++機能にとって重要であると思います。

  • テンプレート。テンプレートパラメータは、アヒル型指定されているので、タイプの構文プロパティは事項は、それほど頻繁に同じテンプレートの両方で使用できるすべてのことであるTT&
    (またはstd::reference_wrapper<T>そのまだへの暗黙のキャストに依存しているT&
    テンプレート、カバーは両方T&T&&も、より一般的です。

  • 左辺値str[0] = 'X';参照なしのステートメントは、c-strings(char* str)に対してのみ機能します。参照によって文字を返すことにより、ユーザー定義クラスが同じ表記を持つことができます。

  • コンストラクターをコピーします。構文的には、オブジェクトへのポインターではなく、コピーコンストラクターにオブジェクトを渡すことは理にかなっています。ただし、コピーコンストラクターがオブジェクトを値で取得する方法はありません。同じコピーコンストラクターが再帰的に呼び出されます。これは、ここでの唯一のオプションとして参照を残します。

  • 演算子のオーバーロード。参照を使用するとoperator+(const T& a, const T& b)、同じ中置記法を保持しながら、演算子呼び出しに間接参照を導入することができます。これは、通常のオーバーロードされた関数でも機能します。

これらのポイントは、C ++と標準ライブラリのかなりの部分に力を与えるため、これは参照の非常に主要なプロパティです。

9
George R 2014-12-28 03:00.

たぶん、いくつかの比喩が役立つでしょう。デスクトップ画面スペースのコンテキストで-

  • 参照では、実際のウィンドウを指定する必要があります。
  • ポインタには、そのウィンドウタイプのインスタンスが0個以上含まれることを保証する画面上のスペースの場所が必要です。
9
Arthur Tacca 2017-11-03 01:16.

ポインターと参照の間には、技術的ではない非常に重要な違いがあります。ポインターによって関数に渡される引数は、非定数参照によって関数に渡される引数よりもはるかに目立ちます。例えば:

void fn1(std::string s);
void fn2(const std::string& s);
void fn3(std::string& s);
void fn4(std::string* s);

void bar() {
    std::string x;
    fn1(x);  // Cannot modify x
    fn2(x);  // Cannot modify x (without const_cast)
    fn3(x);  // CAN modify x!
    fn4(&x); // Can modify x (but is obvious about it)
}

Cに戻ると、次のように見える呼び出しはfn(x)値でのみ渡すことができるため、変更することはできませんx。引数を変更するには、ポインタを渡す必要がありますfn(&x)。したがって、引数の前に&あなたがいない場合、それは変更されないことがわかっていました。(逆は、&変更されたことを意味しますが、constポインターで大きな読み取り専用構造を渡す必要がある場合があるため、正しくありませんでした。)

これはコードを読み取るときに非常に便利な機能constであり、関数がを予期しない場合でも、ポインターパラメーターは非参照ではなく常に変更可能なパラメーターに使用する必要があると主張する人もいますnullptr。つまり、これらの人々は、fn3()上記のような関数シグネチャは許可されるべきではないと主張しています。GoogleのC ++スタイルガイドラインはその一例です。

7
dhokar.w 2017-01-07 04:01.

ポインタと参照の違い

ポインタは0に初期化できますが、参照は初期化できません。実際、参照はオブジェクトも参照する必要がありますが、ポインターはnullポインターにすることができます。

int* p = 0;

しかし、我々は持つことができませんint& p = 0;もしてint& p=5 ;

実際、それを適切に行うには、最初にオブジェクトを宣言して定義してから、そのオブジェクトへの参照を作成できる必要があるため、前のコードの正しい実装は次のようになります。

Int x = 0;
Int y = 5;
Int& p = x;
Int& p1 = y;

もう1つの重要な点は、初期化せずにポインタを宣言できることですが、常に変数またはオブジェクトを参照する必要がある参照の場合、そのようなことはできません。ただし、このようなポインタの使用は危険であるため、通常、ポインタが実際に何かを指しているかどうかを確認します。参照の場合、宣言中にオブジェクトを参照することが必須であることがすでにわかっているため、そのようなチェックは必要ありません。

もう1つの違いは、ポインタが別のオブジェクトを指すことができることですが、参照は常に同じオブジェクトを参照しています。この例を見てみましょう。

Int a = 6, b = 5;
Int& rf = a;

Cout << rf << endl; // The result we will get is 6, because rf is referencing to the value of a.

rf = b;
cout << a << endl; // The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased

別のポイント:STLテンプレートのようなテンプレートがある場合、そのような種類のクラステンプレートは、演算子[]を使用して読みやすくしたり、新しい値を割り当てたりできるように、常にポインターではなく参照を返します。

Std ::vector<int>v(10); // Initialize a vector with 10 elements
V[5] = 5; // Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="
6
Zorgiev 2016-04-25 03:22.

違いは、非定数ポインター変数(定数へのポインターと混同しないでください)はプログラム実行中のある時点で変更される可能性があり、ポインターセマンティクスを使用する必要があります(&、*)演算子、初期化時に参照を設定できますonly(そのため、コンストラクタ初期化子リストでのみ設定できますが、他の方法では設定できません)、通常の値アクセスセマンティクスを使用します。基本的に、非常に古い本で読んだように、演算子のオーバーロードをサポートできるように参照が導入されました。このスレッドで誰かが述べたように、ポインタは0または任意の値に設定できます。0(NULL、nullptr)は、ポインターが何もなしで初期化されることを意味します。nullポインタを逆参照するのはエラーです。ただし、実際には、ポインタに正しいメモリ位置を指していない値が含まれている可能性があります。次に、参照は、常に正しい型の右辺値を指定するため、参照できないものへの参照をユーザーが初期化できないようにします。参照変数を間違ったメモリ位置に初期化する方法はたくさんありますが、これを詳細に掘り下げない方がよいでしょう。マシンレベルでは、ポインタと参照の両方が均一に機能します-ポインタを介して。本質的な参考文献に構文糖衣があるとしましょう。右辺値参照はこれとは異なります-それらは当然スタック/ヒープオブジェクトです。

6
Xitalogy 2019-08-01 22:02.

参照とポインタに関するいくつかの重要な関連詳細

ポインタ

  • ポインター変数は、単項接尾辞宣言演算子を使用して宣言されます*
  • ポインタオブジェクトには、たとえば、配列オブジェクトへの割り当て、&unaryプレフィックス演算子を使用したオブジェクトのアドレス、または別のポインタオブジェクトの値への割り当てによってアドレス値が割り当てられます。
  • ポインタは何度でも再割り当てでき、異なるオブジェクトを指します
  • ポインタは、割り当てられたアドレスを保持する変数です。ターゲットマシンアーキテクチャのアドレスのサイズに等しいメモリ内のストレージを使用します
  • ポインタは、たとえば、インクリメント演算子または加算演算子によって数学的に操作できます。したがって、ポインタなどで繰り返すことができます。
  • ポインターによって参照されるオブジェクトの内容を取得または設定するには、単項接頭演算子*を使用してオブジェクトを逆参照する必要があります。

参考文献

  • 参照は、宣言時に初期化する必要があります。
  • 参照は、単項接尾辞宣言演算子&を使用して宣言されます。
  • 参照を初期化するとき、単項接頭演算子&を必要とせずに、直接参照するオブジェクトの名前を使用します。
  • 初期化されると、割り当てや算術操作によって参照を他の何かにポイントすることはできません。
  • 参照するオブジェクトのコンテンツを取得または設定するために、参照を逆参照する必要はありません。
  • 参照に対する代入操作は、参照自体ではなく、(初期化後に)参照するオブジェクトのコンテンツを操作します(参照する場所は変更されません)。
  • 参照に対する算術演算は、参照自体ではなく、参照するオブジェクトのコンテンツを操作します(参照する場所は変更されません)。
  • ほとんどすべての実装では、参照は実際には参照されたオブジェクトのメモリにアドレスとして格納されます。したがって、ポインタオブジェクトと同じように、ターゲットマシンアーキテクチャのアドレスのサイズに等しいメモリ内のストレージを使用します。

ポインターと参照は「内部」でほぼ同じ方法で実装されますが、コンパイラーはそれらを異なる方法で処理するため、上記のすべての違いが生じます。

論文

私が書いた最近の記事は、ここで示すことができるよりもはるかに詳細であり、この質問、特に記憶の中で物事がどのように起こるかについて非常に役立つはずです:

フードの詳細な記事の下での配列、ポインター、および参照

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

世界最小のマルチツールを15ドルでキーチェーンに追加

世界最小のマルチツールを15ドルでキーチェーンに追加

爪| $ 15 | マルボロ&ケインザクロー| $ 15 | Malboro&Kane世界最小のマルチツールであるTheClawをたった15ドルで手に入れましょう。男の子と一緒に冷たいものを割って開けたり、ネジを締めたり、Amazonパッケージを細断したりする場合でも、この悪い男の子はこれまでで最も便利な製品の1つです。

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンの続編の悪役についてのより多くの噂

ワンダーウーマンとしてのガル・ガドット。WaywardPinesは正式に終了しました。

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

42,000試合で作られた球がスローモーションで燃えるのを見るのは魅力的な光景です

人が2つのマッチを接着するように導くものは何ですか?何があなたをマッチに打ち続け、構造が湾曲していることを発見するのですか?42,000のボールを作るまで、試合を続けなければならない理由は何ですか?しかし、何よりも、これほど魅力的なショーである可能性はどのようにありますか?私はあなたをだますつもりはありません、次に私たちがあなたに残すのは、あなたや私のような人が自由な時間を過ごすことを決定するビデオですボールを作るために必要な試合数を確認します(答えは42です。

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

サクラメントビーが1950万人のカリフォルニア州の有権者記録を漏らし、ハッカーによって即座に侵害された

写真:AP先月、カリフォルニアの地元新聞が1,900万件以上の有権者記録をオンラインで公開しました。Gizmodoは今週、明らかなランサムウェア攻撃中にレコードが侵害されたことを確認しました。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language