谁在传递值时调用复制构造函数?

时间:2014-07-16 11:57:55

标签: c++

我有一个小问题要解决我的问题(也许还有其他人^^)。因此,让我们在C ++中假设以下内容:

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

class B {
  public:
    B() { }
    void foo(A valuePassing) { }
};

int main(int argc, char* argv[])
{
    A passed;
    B obj;

    obj.foo(passed);        

    return EXIT_SUCCESS;
}

在此代码中,谁负责致电A&#39; copy constructor?问题可以概括为:当通过值传递时,谁负责变量,调用者或被调用者的副本?在这种特定情况下,B会在收到var时调用复制构造函数,还是main()会调用它并将副本发送到B方法?< / p>

我的第一个想法是,为了保持C ++可访问性引起的保护,应该是调用者进行复制工作。但我需要确定它。并且每个编译器都很常见(不知道为什么不这样,但编译器之间的差异有时会如此奇怪)?即VC ++和gcc。

提前感谢您的回答;)

编辑:
如果有人想知道,这是关于实施Pass Key pattern创建的Georg Fritzsche。实际上,正如一些人所说,使其不可复制是一个好主意,以防止不太聪明的开发人员制作一个功能,该功能可以为授予密钥的类中的任何人提供密钥。但是使它不可复制也会阻止标准值参数传递(至少它应该,我发现Visual C ++编译器不符合标准,并且实际上可以正常...)

我解决问题的想法是创建一个具有受保护的复制构造函数和赋值运算符的基类PassKey类。然后每个PassKey类都将继承此类。然后,需要使用密钥的函数通过将密钥作为第一个参数。这种方式即使smartass开发人员执行前面提到的功能并提供对密钥的引用,尝试使用它的外部类也无法访问,因为它需要访问密钥{{{{ 1}}只能由受保护和授予的类访问。

我是否足够清楚或者需要澄清一下? :S

3 个答案:

答案 0 :(得分:2)

obj.foo(passed);将导致由编译器生成的以下步骤序列:

  1. obj的指针放在堆栈框架(this参数)
  2. 创建一个temp变量(这是调用复制构造函数的地方)
  3. temp放入堆栈框架
  4. 拨打foo()
  5. 从函数返回后 - 清理堆栈(这是调用析构函数的地方)

答案 1 :(得分:0)

现在我会尽可能地回答。

简短的回答是调用构造函数是编译器的工作。据我所知,它也将由呼叫者构建。但是,具体如何完成此操作可能取决于您正在使用的调用约定。

存在许多调用约定,一个编译器可能支持多个,例如参见this page at MSDN。不同的架构可能需要特定的约定。

对于x86,一个调用约定就像YePhIck回答的那样,而在例如ARM平台上,地址将在分支到函数之前直接放在寄存器中。而不是被推到堆栈中(除非你有超过4个参数)。

被调用者是否有责任复制该对象?我不知道这样的调用约定,但它可能存在。

答案 2 :(得分:0)

那么,B类如何自行调用函数?复制构造函数调用只有两个位置:main()和foo()。我无法看到来自foo的任何电话,所以答案显而易见。 并且不要忘记foo()的返回类型。