使用临时成员初始化成员时,如何确保对临时构造函数的单一调用?
When initialising member with temporary, how to ensure a single call to temporary's constructor?
假设我有一个包装器:
template<typename T>
struct Outer {
T inner;
...
};
,我想创建一个 Outer
包装一个 Inner
,像这样:
Outer<Inner> wrapper(Inner(...)); // Inner object is a temporary
是否可以声明 Outer
/Inner
以便从临时 Inner
创建 Outer
对象仅涉及构建单个 Inner
目的?我尝试为 Inner
声明移动构造函数,并让 Outer
获取对 Inner
的右值引用,甚至在临时但仍然是 2 个副本上显式调用 std::move
Inner
已创建:
#include <stdio.h>
#include <utility>
template<typename T>
struct Outer {
T inner;
Outer(T&& inner) : inner(inner) {}
};
struct Inner {
int x;
int y;
Inner(const int x, const int y) : x(x), y(y) { printf("ctor\n"); }
Inner(const Inner& rhs) : x(rhs.x), y(rhs.y) { printf("copy ctor\n"); }
Inner(Inner&& rhs) : x(std::exchange(rhs.x, 0)), y(std::exchange(rhs.y, 0)) {
printf("move ctor\n");
}
Inner& operator=(const Inner& rhs) {
printf("assign\n");
return *this = Inner(rhs);
}
Inner& operator=(Inner&& rhs) {
printf("move assign\n");
std::swap(x, rhs.x);
std::swap(y, rhs.y);
return *this;
}
~Inner() { printf("dtor\n"); }
};
int main() {
Outer<Inner> wrapper(Inner(123, 234));
// SAME: Outer<Inner> wrapper(std::move(Inner(123, 234)));
return 0;
}
输出:
ctor <-- The temporary
copy ctor <-- Yet another instance, from the temporary
dtor
dtor
如上所示,创建一个Outer
个实例就创建了2个Inners
。这看起来很奇怪,因为我认为可以省略临时文件,或者至少调用移动构造函数。是否可以使用单个 Inner
构造来实例化 Outer
?
我猜你正在寻找这个:
#include <stdio.h>
#include <utility>
template <typename T> struct Outer {
T inner;
// Outer(T &&inner) : inner(std::move(inner)) {}
template <class... Args> Outer(Args &&...args) :inner(args...) {}
};
struct Inner {
int x;
int y;
Inner(const int x, const int y) : x(x), y(y) { printf("ctor\n"); }
Inner(const Inner &rhs) : x(rhs.x), y(rhs.y) { printf("copy ctor\n"); }
Inner(Inner &&rhs)
: x(std::exchange(rhs.x, 0)), y(std::exchange(rhs.y, 0)) {
printf("move ctor\n");
}
Inner &operator=(const Inner &rhs) {
printf("assign\n");
return *this = Inner(rhs);
}
Inner &operator=(Inner &&rhs) {
printf("move assign\n");
std::swap(x, rhs.x);
std::swap(y, rhs.y);
return *this;
}
~Inner() { printf("dtor\n"); }
};
int main() {
Outer<Inner> wrapper(123, 234);
// SAME: Outer<Inner> wrapper(std::move(Inner(123, 234)));
return 0;
}
假设我有一个包装器:
template<typename T>
struct Outer {
T inner;
...
};
,我想创建一个 Outer
包装一个 Inner
,像这样:
Outer<Inner> wrapper(Inner(...)); // Inner object is a temporary
是否可以声明 Outer
/Inner
以便从临时 Inner
创建 Outer
对象仅涉及构建单个 Inner
目的?我尝试为 Inner
声明移动构造函数,并让 Outer
获取对 Inner
的右值引用,甚至在临时但仍然是 2 个副本上显式调用 std::move
Inner
已创建:
#include <stdio.h>
#include <utility>
template<typename T>
struct Outer {
T inner;
Outer(T&& inner) : inner(inner) {}
};
struct Inner {
int x;
int y;
Inner(const int x, const int y) : x(x), y(y) { printf("ctor\n"); }
Inner(const Inner& rhs) : x(rhs.x), y(rhs.y) { printf("copy ctor\n"); }
Inner(Inner&& rhs) : x(std::exchange(rhs.x, 0)), y(std::exchange(rhs.y, 0)) {
printf("move ctor\n");
}
Inner& operator=(const Inner& rhs) {
printf("assign\n");
return *this = Inner(rhs);
}
Inner& operator=(Inner&& rhs) {
printf("move assign\n");
std::swap(x, rhs.x);
std::swap(y, rhs.y);
return *this;
}
~Inner() { printf("dtor\n"); }
};
int main() {
Outer<Inner> wrapper(Inner(123, 234));
// SAME: Outer<Inner> wrapper(std::move(Inner(123, 234)));
return 0;
}
输出:
ctor <-- The temporary
copy ctor <-- Yet another instance, from the temporary
dtor
dtor
如上所示,创建一个Outer
个实例就创建了2个Inners
。这看起来很奇怪,因为我认为可以省略临时文件,或者至少调用移动构造函数。是否可以使用单个 Inner
构造来实例化 Outer
?
我猜你正在寻找这个:
#include <stdio.h>
#include <utility>
template <typename T> struct Outer {
T inner;
// Outer(T &&inner) : inner(std::move(inner)) {}
template <class... Args> Outer(Args &&...args) :inner(args...) {}
};
struct Inner {
int x;
int y;
Inner(const int x, const int y) : x(x), y(y) { printf("ctor\n"); }
Inner(const Inner &rhs) : x(rhs.x), y(rhs.y) { printf("copy ctor\n"); }
Inner(Inner &&rhs)
: x(std::exchange(rhs.x, 0)), y(std::exchange(rhs.y, 0)) {
printf("move ctor\n");
}
Inner &operator=(const Inner &rhs) {
printf("assign\n");
return *this = Inner(rhs);
}
Inner &operator=(Inner &&rhs) {
printf("move assign\n");
std::swap(x, rhs.x);
std::swap(y, rhs.y);
return *this;
}
~Inner() { printf("dtor\n"); }
};
int main() {
Outer<Inner> wrapper(123, 234);
// SAME: Outer<Inner> wrapper(std::move(Inner(123, 234)));
return 0;
}