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));涉及两个构造函数:一个采用int(从整数 5 隐式转换)和复制构造函数。这里不涉及赋值运算符。

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

但是,从概念上讲,编译器需要检查是否存在可访问且合适的复制构造函数。如果 a) 复制构造函数是私有的/受保护的(不可访问)或 b) 复制构造函数通过CTest b = 5;非常量引用获取参数(不能接受临时来自CTest(5)- VC++ 可能将其作为非-标准编译器扩展,虽然)。

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

于 2010-05-17T11:42:22.950 回答