8

これはばかげた質問かもしれませんが、それでも少し興味があります...最近、以前の同僚のプロジェクトの1つに取り組んでいて、彼が次のようなものを使用するのが本当に好きであることに気付きました。

int foo(7);

それ以外の:

int foo = 7;

これはC++言語で行う通常の/良い方法ですか?それにはある種の利点がありますか?(または、これは彼が夢中になっていたばかげたプログラミングスタイルですか..?

これは、クラスコンストラクターでクラスメンバー変数を割り当てる方法を少し思い出させてくれます...次のようなものです。

class MyClass
{
public:
   MyClass(int foo) : mFoo(foo)
   { }

private:
   int   mFoo;
};

これの代わりに:

class MyClass
{
public:
   MyClass(int foo)
   {
      mFoo = foo; 
   }

private:
   int   mFoo;
};
4

8 に答える 8

10

基本タイプの場合、違いはありません。既存のコードと一致し、より自然に見える方を使用してください。

さもないと、

A a(x);

直接初期化を実行し、

A a = x;

コピーの初期化を実行します。

2番目の部分はメンバー初期化リストです。StackOverflowにはそれに関するQ&Aがたくさんあります。

于 2012-09-05T15:46:04.093 に答える
4

どちらも有効です。組み込み型の場合、同じことを行います。クラスタイプの場合、微妙な違いがあります。

MyClass m(7);  // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
               // then uses MyClass(const MyClass&) to copy the
               // temporary object into n

明らかな意味は、MyClassコピーコンストラクターがない場合、またはコピーコンストラクターはあるがアクセスできない場合、試行された構築は失敗するということです。構築が成功した場合、コンパイラーはコピーコンストラクターをスキップしてMyClass(int)直接使用することができます。

于 2012-09-05T15:47:50.660 に答える
3

上記のすべての答えは正しいです。これに、C ++ 11が別の方法、つまり変数を初期化するための一般的な方法をサポートしていることを追加してください。

int a = {2} ;

また

int a {2} ;
于 2012-09-05T15:49:56.243 に答える
2

これは変数を初期化するC++スタイルです。C++は基本型に追加したため、基本型とユーザー定義型に同じ形式を使用できます。これは、どちらの種類のタイプでもインスタンス化することを目的としたテンプレートコードにとって非常に重要です。

基本型の通常の初期化に使用するかどうかは、スタイル設定です。

C ++ 11は、すべての型に同じスタイルの初期化を使用できるようにする統一初期化構文も追加することに注意してください。POD構造体や配列などの集合体も含まれます(ただし、ユーザー定義型には、統一構文を使用できるようにする初期化リスト)。

于 2012-09-05T15:46:33.080 に答える
2

ClassType v(<constructor args>)他のいくつかの良い答えは、「インプレース」の構築( )と一時オブジェクトの作成とそれをコピーするためのコピーコンストラクターの使用()の違いを指摘していますClassType v = <constructor arg>。さらに2つのポイントが必要だと思います。まず、2番目の形式には明らかに引数が1つしかないため、コンストラクターが複数の引数を取る場合は、最初の形式を選択する必要があります(はい、それを回避する方法はありますが、直接構文の方が簡潔で読みやすいと思いますが、 、指摘されているように、それは個人的な好みです)。

次に、コピーコンストラクターが標準のコンストラクターと大幅に異なることを行う場合は、使用するフォームが重要になります。これはほとんどの場合当てはまらないでしょうし、そうするのは悪い考えだと主張する人もいますが、言語はこれを可能にします(しかし、それが原因であなたが対処することになったすべての驚きですが、あなた自身のせいです)。

于 2012-09-05T15:54:09.483 に答える
2

物事は見た目ほど単純ではないので、あなたの質問はまったくばかげた質問ではありません。あなたが持っているとしましょう:

class A {
  public:
    A() {}
};

class B {
  public:
    class B(A const &) {}
};

書き込み

B b = B(A());

Bのコピーコンストラクターにアクセスできる必要があります。書き込み

B b = A();

また、Bの変換コンストラクターB(A const&)が明示的に宣言されていないことも必要です。一方、あなたが書く場合

A a;
B b(a);

すべてが順調ですが、あなたが書くなら

B b(A());

これは、コンパイラによって、Aを返すパラメータのない関数である名前のない引数を取る関数bの宣言として解釈され、不思議なバグが発生します。これは、C++の最も厄介な解析として知られています。

于 2012-09-05T16:08:52.237 に答える
2

私は括弧で囲まれたスタイルを使用することを好みます...私は常にスペースを使用して、スペースを使用しない関数またはメソッド呼び出しと区別します。

int foo (7); // initialization
myVector.push_back(7); // method call

初期化のためにこれを全面的に使用することを好む私の理由の1つは、それが割り当てではないことを人々に思い出させるのに役立つからです。したがって、代入演算子へのオーバーロードは適用されません。

#include <iostream>

class Bar {
private:
    int value;
public:
    Bar (int value) : value (value) {
        std::cout << "code path A" << "\n";
    }
    Bar& operator=(int right) {
        value = right;
        std::cout << "code path B" << "\n";
        return *this;
    }
};

int main() {
    Bar b = 7;
    b = 7;
    return 0;
}

出力は次のとおりです。

code path A
code path B

等号の存在が違いを覆い隠しているように感じます。それが「常識」であっても、初期化は割り当てとは著しく異なって見えるようにするのが好きです。そうすることができるからです。

于 2012-09-05T16:12:57.040 に答える
1

これは、何かを初期化するための構文にすぎません:-

SomeClass data(12, 134);

それは合理的に見えますが、

int data(123);

奇妙に見えますが、同じ構文です。

于 2012-09-05T15:43:29.160 に答える