式のreturnステートメントによってコピーコンストラクターが呼び出されるのはなぜですか?

ZaellixA

カスタムクラスの加算演算子を実装しています。呼び出される関数/演算子は、フレンド関数でもメンバー関数でもないため、ベクトルにスカラー値を追加します(クラスは線形代数ベクトルクラスであると想定されています)。内部的には、この関数はクラスの加算演算子を呼び出し、次に同じクラスの複合加算を呼び出します。

以下は、クラスの宣言の関連部分(これはテンプレートクラスです)と、コンストラクター、非メンバー関数/演算子、および複合加算演算子の実装です(加算演算子は以下に続き、「問題」を示します。 ")。

template<class T>
class Vector {
  public:
    Vector(const unsigned long length); // Default ctor
    Vector(const Vector<T>& vec); // Copy ctor

    template<class S>
    Vector<T> operator +(const S& scalar);
    
    template<class S>
    Vector<T>& operator +=(const S& scalar);

  private:
    unsigned long mLen;
    T* mData;
};

template<class T, class S>
Vector<T> operator +(const S& scalar, const Vector<T>& vec);

// Implementation of ctors
template<class T>
Vector<T>::Vector(const unsigned long length) {
  mLen = length;
  mData = new T[length];
}

template<class T>
Vector<T>::Vector(const Vector<T>& vec) {
  mLen = vec.mLen;
  std::copy_n(vec.mData, vec.mLen, mData);
}

template<class T, class S>
Vector<T> operator +(const S& scalar, const Vector<T>& vec) {
  return vec + scalar;
}

template<class T> template<class S>
Vector<T>& Vector<T>::operator +=(const S& scalar) {
  for(unsigned long i = 0; i < mLen; ++i) {
    mData[i] += scalar;
  }

  return *this;
}

すでに述べたように、実装は複合代入演算子に基づいています。すべての演算子は、結果ワイズ、意図したとおりに機能しているように見える、しかし、私は複合代入演算の結果を返す際に直接コピーコンストラクタが呼び出され、私はその理由を理解することはできません。説明については、次の例を参照してください。

  1. コピーコンストラクターが呼び出される例
template<class T> template<class S>
Vector<T> Vector<T>::operator +(const S& scalar) {
  Vector<T> result(*this); // Normal copy ctor call
  return result += scalar; // Here the copy ctor is invoked again!!!
}
  1. コピーコンストラクターが呼び出されない例
// Implementation of the addition operators
template<class T> template<class S>
Vector<T> Vector<T>::operator +(const S& scalar) {
  Vector<T> result(*this); // Normal copy ctor call
  result += scalar;
  return result; // Here the copy ctor is NOT invoked
}

main.cpp例では、次の可能性

int main(int argc, const char* argv[]) {
  Vector<T> vec(10);
  1 + vec;
}

ここで、加算演算子の最初の実装が使用されると、コピーコンストラクターがreturnステートメントで呼び出されます(上記の行に加えて、明らかに完全に理にかなっています)。演算子が2番目の方法で実装されている場合、上記の行で明示的に呼び出された場合、コピーコンストラクターは1回だけ呼び出されます。

私はXCode11.3.1を使用しています(Macでは明らかに)。この問題についてさらに情報が必要な場合はお知らせください。誰かがここで光を当てることができれば、私は感謝するでしょう。

1201ProgramAlarm

以来operator+=戻って参照、return文は関数の戻り値には、この参照値をコピーする必要があります。コンパイラーがコピーコンストラクターへのこの呼び出しを排除するために使用できる値はありません。

あなたの最初の例は同等です

template<class T> template<class S>
Vector<T> Vector<T>::operator +(const S& scalar) {
  Vector<T> result(*this);
  Vector<T> &ans = (result += scalar);  // (Parens included for clarity)
  return ans;
}

これにより、コンパイラがreturnステートメントでコピーコンストラクタを呼び出さなければならない理由がより明確になります。

2番目の例では、ローカルをresult直接返すため、コピーコンストラクターの呼び出しは省略されます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

コピーコンストラクターが次のステートメントで呼び出されるのはなぜですか:myVector.push_back(A());

分類Dev

コピーの初期化:コピーの省略がオフになっているのに、移動またはコピーコンストラクターが呼び出されなかったのはなぜですか?

分類Dev

コピーコンストラクタが呼び出されるのはなぜですか?

分類Dev

移動コンストラクターではなくコピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

コピーコンストラクタと移動コンストラクタが一緒に呼び出されるのはなぜですか?

分類Dev

値によって関数に渡されたときと別のコンストラクターに値によって渡されたときのコンストラクターの呼び出しに違いがあるのはなぜですか?

分類Dev

代入演算子の後にこのコードでコピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

関数が戻ったときにコピーコンストラクターが呼び出されないのはなぜですか?

分類Dev

コピーコンストラクタが呼び出されたのはなぜですか?

分類Dev

オブジェクトをパラメーターとして渡すときに、デストラクタが呼び出されているのにコンストラクションが呼び出されていないのはなぜですか?

分類Dev

このコードスニペットでコピーコンストラクターが2回呼び出されるのはなぜですか?

分類Dev

テンプレート化されたコピーコンストラクタが呼び出されないのはなぜですか?

分類Dev

std :: string moveコンストラクターが呼び出されなかったのはなぜですか?

分類Dev

移動コンストラクターが呼び出されなかったのはなぜですか?

分類Dev

`unique_ptr`の移動中にコピーコンストラクターがラムダで呼び出されるのはなぜですか?

分類Dev

コピーを行う前にデストラクタが呼び出されるのはなぜですか?

分類Dev

単純なコンストラクターが呼び出された後にコピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

以下のコードでコピーコンストラクターが2回呼び出されるのはなぜですか?

分類Dev

参照によって渡されたにもかかわらず、演算子+オーバーロードがコピーコンストラクターを呼び出すのはなぜですか?

分類Dev

ASPX-パラメーター化されたコンストラクターをスキップして、パラメーターなしのコンストラクターが呼び出されるのはなぜですか?

分類Dev

C ++なぜコピーコンストラクタが呼び出されたのですか?

分類Dev

初期化子、コンストラクター、およびメソッド呼び出しを使用するときに、printステートメントがこの順序で実行されるのはなぜですか?

分類Dev

Java-インスタンスブロックがコンストラクターの後に呼び出されるのはなぜですか、またはコンストラクター内で順序的に呼び出されるのですか?

分類Dev

子クラスのコンストラクターが呼び出されないのはなぜですか?

分類Dev

Cupsクラスのコンストラクターが呼び出されないのはなぜですか?

分類Dev

コンストラクターが2回目に呼び出されないのはなぜですか?

分類Dev

このコンストラクターが 2 回呼び出されるのはなぜですか?

分類Dev

C ++で作成済みのオブジェクトに実際にコピーしているのに、コピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

ここでmoveコンストラクターが呼び出されるのはなぜですか?

Related 関連記事

  1. 1

    コピーコンストラクターが次のステートメントで呼び出されるのはなぜですか:myVector.push_back(A());

  2. 2

    コピーの初期化:コピーの省略がオフになっているのに、移動またはコピーコンストラクターが呼び出されなかったのはなぜですか?

  3. 3

    コピーコンストラクタが呼び出されるのはなぜですか?

  4. 4

    移動コンストラクターではなくコピーコンストラクターが呼び出されるのはなぜですか?

  5. 5

    コピーコンストラクタと移動コンストラクタが一緒に呼び出されるのはなぜですか?

  6. 6

    値によって関数に渡されたときと別のコンストラクターに値によって渡されたときのコンストラクターの呼び出しに違いがあるのはなぜですか?

  7. 7

    代入演算子の後にこのコードでコピーコンストラクターが呼び出されるのはなぜですか?

  8. 8

    関数が戻ったときにコピーコンストラクターが呼び出されないのはなぜですか?

  9. 9

    コピーコンストラクタが呼び出されたのはなぜですか?

  10. 10

    オブジェクトをパラメーターとして渡すときに、デストラクタが呼び出されているのにコンストラクションが呼び出されていないのはなぜですか?

  11. 11

    このコードスニペットでコピーコンストラクターが2回呼び出されるのはなぜですか?

  12. 12

    テンプレート化されたコピーコンストラクタが呼び出されないのはなぜですか?

  13. 13

    std :: string moveコンストラクターが呼び出されなかったのはなぜですか?

  14. 14

    移動コンストラクターが呼び出されなかったのはなぜですか?

  15. 15

    `unique_ptr`の移動中にコピーコンストラクターがラムダで呼び出されるのはなぜですか?

  16. 16

    コピーを行う前にデストラクタが呼び出されるのはなぜですか?

  17. 17

    単純なコンストラクターが呼び出された後にコピーコンストラクターが呼び出されるのはなぜですか?

  18. 18

    以下のコードでコピーコンストラクターが2回呼び出されるのはなぜですか?

  19. 19

    参照によって渡されたにもかかわらず、演算子+オーバーロードがコピーコンストラクターを呼び出すのはなぜですか?

  20. 20

    ASPX-パラメーター化されたコンストラクターをスキップして、パラメーターなしのコンストラクターが呼び出されるのはなぜですか?

  21. 21

    C ++なぜコピーコンストラクタが呼び出されたのですか?

  22. 22

    初期化子、コンストラクター、およびメソッド呼び出しを使用するときに、printステートメントがこの順序で実行されるのはなぜですか?

  23. 23

    Java-インスタンスブロックがコンストラクターの後に呼び出されるのはなぜですか、またはコンストラクター内で順序的に呼び出されるのですか?

  24. 24

    子クラスのコンストラクターが呼び出されないのはなぜですか?

  25. 25

    Cupsクラスのコンストラクターが呼び出されないのはなぜですか?

  26. 26

    コンストラクターが2回目に呼び出されないのはなぜですか?

  27. 27

    このコンストラクターが 2 回呼び出されるのはなぜですか?

  28. 28

    C ++で作成済みのオブジェクトに実際にコピーしているのに、コピーコンストラクターが呼び出されるのはなぜですか?

  29. 29

    ここでmoveコンストラクターが呼び出されるのはなぜですか?

ホットタグ

アーカイブ