5

この場合、どちらがコンストラクターまたは代入演算子と呼ばれるかを説明するC++標準の定義がありますか。

#include <iostream>

using namespace std;

class CTest
{
public:

 CTest() : m_nTest(0)
 {
  cout << "Default constructor" << endl;
 }

 CTest(int a) : m_nTest(a)
 {
  cout << "Int constructor" << endl;
 }

 CTest(const CTest& obj)
 {
  m_nTest = obj.m_nTest;
  cout << "Copy constructor" << endl;
 }

 CTest& operator=(int rhs)
 {
  m_nTest = rhs;
  cout << "Assignment" << endl;
  return *this;
 }

protected:
 int m_nTest;
};

int _tmain(int argc, _TCHAR* argv[])
{
 CTest b = 5;

 return 0;
}

それとも、コンパイラの最適化の問題ですか?

4

3 に答える 3

12

intこの場合に呼び出されるのは、常にデフォルトのコンストラクターです。これは暗黙的な変換と呼ばれ、意味的には次のコードと同等です。

CTest b(5);

代入演算子は、初期化で呼び出されることはありません。次の場合を考えてみましょう。

CTest b = CTest(5);

ここでは、コンストラクターをint明示的に呼び出し(を取得)、結果をに割り当てbます。しかし、繰り返しになりますが、代入演算子は呼び出されませ。厳密に言えば、どちらの場合も、タイプのオブジェクトを作成した後にコピーコンストラクターを呼び出しますCTest。しかし実際には、この標準はコンパイラーがここでコピーコンストラクター呼び出しを最適化することを積極的に推奨しています(§12.8/ 15)。実際には、最新のC++コンパイラーはここでcopycon呼び出しを発行しません。

于 2010-05-17T09:11:40.307 に答える
7

ここで何が起こっているかは、コンパイラによって少し異なります。intコンストラクターを使用して一時オブジェクトを作成し、その一時コンストラクターからコンストラクトbをコピーすることができます。ただし、コピーコンストラクターの呼び出しがなくなる可能性があります。どちらの場合も、代入演算子は使用されません。

于 2010-05-17T09:18:38.193 に答える
4

CTest b = 5;CTest b(CTest(5));は、 2つのコンストラクターが関係しているのとまったく同じです。1つはint(整数5から暗黙的に変換)を取り、もう1つはコピーコンストラクターです。代入演算子はここでは一切関与しません。

コンパイラは不要なコピーを最適化する可能性があるため、結果は入力したかのようになりますCTest b(5)。したがって、実行時に、「コピーコンストラクタ」-fno-elide-constructorsが出力されるか(オプション付きのGCC)、表示されないか(デフォルトではGCC)の両方がプログラムの有効な出力になります。

ただし、概念的には、コンパイラは、アクセス可能で適切なコピーコンストラクタが存在するかどうかを確認する必要があります。CTest b = 5;a)コピーコンストラクターがプライベート/保護されている(アクセスできない)場合、またはb)コピーコンストラクターが非定数参照によって引数を取る(からの一時的なものを受け入れることができないCTest(5)-VC++はそれを非として受け入れる可能性がある)場合、フォームはコンパイルに失敗します-ただし、標準のコンパイラ拡張機能)。

士気は次のとおりです。コードを見て、プログラム内でコピーコンストラクターがどこで何回呼び出されたかを簡単に判断する方法はありません。多くの場合、コピーは省略できます。したがって、コピーコンストラクターの副作用に依存しないでください。本来の機能を実行する場合、コンパイラーが不要なコピーコンストラクターの呼び出しを排除しても問題ありません。

于 2010-05-17T11:42:22.950 に答える