在调用委托构造函数时避免复制

时间:2018-01-02 22:52:21

标签: c++

具有委托构造函数的类

class A {
  A(SomeObject obj,   // requires a new copy of the object 
    int x,
    const string& y
  ) { // additional logic }
  A(SomeObject obj, const string& y)   
    :A(obj, 0, y) {}     // will obj be copied?
};

目标用途:

SomeObject obj;
A a1(obj, "first");
A a2(obj, "second");

设计是在执行SomeObject的构造时恰好构造A一次。 在委托给另一个构造函数时,传递obj会导致另一个SomeObject被复制构造吗?如果是,我该如何避免呢?

2 个答案:

答案 0 :(得分:9)

是的,在委托给其他构造函数时会复制obj:这不是copy elisionautomatic moving的允许上下文。

解决方案是将std::move应用于成员初始化列表中的参数,或者(对于 私有目标构造函数)通过​​非const引用接收对象。其中任何一个都允许(公共)构造函数仍然按值接收其参数,就像C ++ 11推荐一样。

答案 1 :(得分:-6)

没有。它不会从一个构造函数复制到另一个。您似乎假设一个构造函数将初始化对象然后将其传递给另一个,但情况并非如此。请参阅standard

中的这句话
  

mem-initializer-list可以使用表示构造函数类本身的任何class-or-decltype委托给构造函数类的另一个构造函数。如果mem-initializer-id指定构造函数的类,它应该是唯一的mem-initializer;构造函数是委托构造函数,mem-initializer选择的构造函数是目标构造函数。目标构造函数由重载决策选择。目标构造函数返回后,将执行委托构造函数的主体。如果构造函数直接或间接地委托给自己,则程序格式错误,无需诊断。

此最小示例显示Copied仅打印一次:

#include <iostream>

struct Foo {
    Foo() = default;
    Foo(const Foo&) {
        std::cout << "Copied";
    }
};

struct A {
    A(Foo f, int i) { }
    A(Foo f) : A(f, 0) { }
};

int main() {
    A a{Foo{}};
}