构造函数或赋值运算符

时间:2010-05-17 09:10:16

标签: c++ copy-constructor assignment-operator

你能帮助我吗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;
}

或者仅仅是编译器优化的问题?

3 个答案:

答案 0 :(得分:11)

它始终是默认构造函数,在这种情况下调用int。这称为隐式转换,在语义上等效于以下代码:

CTest b(5);

在初始化中,从不调用赋值运算符。考虑以下情况:

CTest b = CTest(5);

在这里,我们显式调用构造函数(带int),然后将结果赋给b。但是再一次,没有任何赋值运算符永远被调用。严格地说,两种情况都会在创建类型为CTest的对象后调用复制构造函数。但事实上,该标准积极鼓励编译器在这里优化复制构造函数调用(§12.8/ 15) - 实际上,现代C ++编译器不会在这里发出copycon调用。

答案 1 :(得分:7)

这里发生的事情取决于您的编译器。它可以使用int构造函数创建一个临时对象,然后从该临时文件复制构造b。但是,它很可能会忽略复制构造函数调用。在任何情况下都不会使用赋值运算符。

答案 2 :(得分:4)

CTest b = 5;完全等同于CTest b(CTest(5));涉及两个构造函数:一个采用int(隐式转换为整数5)和复制构造函数。赋值运算符绝不参与此处。

编译器可能会优化出不必要的副本,因此结果就像您键入了CTest b(5)一样。因此,在运行时,看到“复制构造函数”打印(带有-fno-elide-constructors选项的GCC)或不打印(默认情况下为GCC)都是程序的有效输出。

但是,从概念上讲,编译器需要检查是否存在可访问且合适的复制构造函数。如果a)复制构造函数是private / protected(不可访问)或b)复制构造函数通过非const引用接受参数(不能接受来自{{1的临时),则CTest b = 5;形式将无法编译但是 - VC ++可能会接受它作为非标准编译器扩展。)

士气是:没有简单的方法可以通过查看代码来判断程序中复制构造函数的调用位置和次数。复制通常可以省略,因此您不应该依赖复制构造函数的副作用。如果它完成它应该做的事情,那么如果编译器消除了一些不必要的复制构造函数调用,那么对你来说无关紧要。