c ++ 11为调用者构造一个对象

Ale*_*lec 1 c++ move-semantics c++11

我有一些Foo结构需要知道其他对象的状态要初始化,所以我为它创建一个工厂方法:

struct Foo {
  Foo(int x) : x_(x) {}

  int x_;
};

struct FooFactory {
  Foo MakeFoo() {
    return Foo(++counter);
  }

  int counter = 0;
};
Run Code Online (Sandbox Code Playgroud)

因此,虽然呼叫者可以这么做Foo(++factory.counter),但能够说出来更清洁factory.MakeFoo().

但是这段代码需要复制,并说我们想避免这种情况.我们可以使用移动构造函数.

struct Foo {
  Foo(int x) : x_(x) {}
  Foo(Foo& foo) = delete;
  Foo(Foo&& foo) : Foo(foo.x_) { foo.x_ = 0; }

  int x_;
};

struct FooFactory {
  Foo MakeFoo() {
    return Foo(++counter);
  }

  int counter = 0;
};
Run Code Online (Sandbox Code Playgroud)

哪个有效,但看起来仍然比我想要的"更多".类似的东西Foo foo = factory.MakeFoo()仍然会创建一个临时的内部,MakeFoo()然后foo通过其移动构造函数进行构造.

有没有写这个,这样的方式MakeFoo构建直接什么它被分配到?

eca*_*mur 8

是的,使用braced-init-list返回直接初始化目标对象:

struct FooFactory {
  Foo MakeFoo() {
    return {++counter};
  }
  // ...
};
Run Code Online (Sandbox Code Playgroud)

请注意,如果的1参数的构造函数这是不行Fooexplicit.

6.6.3 [stmt.return]:

[...]带有braced-init-list的return语句通过copy-list-initialization(8.5.4)从指定的初始化列表初始化要从函数返回的对象或引用.[...]

  • @ Manu343726将没有副本省略,因为没有副本.这*直接初始化*返回值.例如,它甚至可以使用不可复制的不可移动类型. (3认同)