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

C++ 在调用委托构造函数时避免复制,c++,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? }; 目标用途: Some

具有委托构造函数的类

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
在委托给另一个构造函数时被复制构造?如果是,我如何避免它?

否。它不会从一个构造函数复制到另一个构造函数。您似乎假设一个构造函数将初始化对象,然后将其传递给另一个,但事实并非如此。请参见以下引用:

mem初始值设定项列表可以使用表示构造函数类本身的任何类或decltype委托给构造函数类的另一个构造函数。如果mem初始值设定项id指定了构造函数的类,则它应是唯一的mem初始值设定项;构造函数是一个委托构造函数,mem初始值设定项选择的构造函数是目标构造函数。通过重载解析选择目标构造函数。一旦目标构造函数返回,将执行委托构造函数的主体。如果构造器直接或间接地委托给它自己,则程序是错误的,不需要诊断

此最小示例显示仅打印一次的
复制的

#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{}};
}
#包括
结构Foo{
Foo()=默认值;
Foo(const Foo&){

std::coutYes,
obj
在委托给另一个构造函数时被复制:这不是允许的上下文,甚至对于

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

@DragonThinks,浅层与深层在很大程度上取决于
SomeObject
类。如果您使用委托构造函数,为什么不创建另一个构造函数来接受对
SomeObject
的引用,这两个现有构造函数都委托了该构造函数也许
SomeObject obj
->
const SomeObject&obj
@cwschmidt我看不出有什么重大变化。@cwschmidt问题一直是,既然第一个副本是设计好的,是否会有一个额外的副本。@user9163035为什么你认为
obj
还没有初始化?更改你的
a{Foo{};
to
foof;A{f};
使复制构造函数被调用两次。您的示例使用了保证的复制省略,因为
C++17
above@user9163035:您在外部构造函数调用中观察到复制省略。@user4581301,您也可以进行空引用,但两者都是未定义的行为,所以事实上,你可能会失去一些意义。你可以尝试复制一个未初始化的对象,但你不能保证它真的会发生。据我所知,
tt(t);
合法的类型只有
无符号字符
std::byte
。(虽然我不确定这一限制背后的动机是什么。)@chris我认为带有
T(T);
和用户提供的复制构造函数的代码是正确的,只要复制构造函数没有提到任何与之相关的非静态数据成员(或基类):