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

Avoid copying when calling delegating constructors

本文关键字:复制 构造函数 调用      更新时间:2023-10-16

具有委托构造函数的类

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");

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

是的,obj在委托给另一个构造函数时被复制:这不是复制 elision 甚至自动移动的允许上下文。

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

No.它不会从一个构造函数复制到另一个构造函数。您似乎假设一个构造函数将初始化对象,然后将其传递给另一个构造函数,但事实并非如此。请参阅标准中的这句话:

mem-initializer-list 可以使用表示构造函数的类本身的任何类或 decltype 委托给构造函数类的另一个构造函数。如果 mem-initializer-id 指定构造函数的类,它应该是唯一的 mem 初始值设定项;构造函数是委托构造函数,MEM 初始值设定项选择的构造函数是目标构造函数。目标构造函数是通过重载解析选择的。目标构造函数返回后,将执行委托构造函数的主体。如果构造函数直接或间接委托给自身,则程序格式不正确,无需诊断。

这个最小的示例显示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{}};
}