我的一个朋友偶然发现了一个问题
是否有任何方法可以返回可复制但不可移动的对象副本。换句话说,我们可以使以下代码工作吗?
struct A {
A() = default;
A(A const&) = default; // copyable
A& operator=(A const&) = default; // assignable
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A() = default;
};
A foo() {
A a;
return a;
}
int main() {
A a(foo()); //will fail, because it calls A(A&&)
return 0;
}
在我看来,我们不能,因为foo()
是A&&
,因此编译器必须调用A(A&&)
。但我想要一些确认。
答案 0 :(得分:3)
来自dyp发布的评论中的代码; Is there a cast (or standard function) with the opposite effect to std::move
?,以下代码段编译。
我不确定代码是否有用,在linked post中讨论了这是否是一个好主意。
struct A {
A() = default;
A(A const&) = default; // copyable
A& operator=(A const&) = default; // assignable
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A() = default;
};
template <typename T>
T& as_lvalue_ref(T&& t) {
return t;
}
A foo() {
A a;
return as_lvalue_ref(a);
}
int main() {
A a(as_lvalue_ref(foo()));
return 0;
}
代码示例here。
static_cast<T&>()
代替as_lvalue_ref()
也可以起作用,甚至可能更好(尽管看起来很笨拙),因为它实际上是冗长的。在返回引用的任何情况下,都可能发生悬空引用。在这种情况下给出签名A foo()
(而不是说A& foo()
),这里没有悬空引用,返回了A
的完整对象。行A a(as_lvalue(foo()));
没有悬空引用,因为从as_lvalue_ref(foo())
返回的临时(prvalue)在表达式结束前保持有效(;
),然后a
对象将然后形成良好。
答案 1 :(得分:0)
有人带着那段代码来到另一个论坛。它不应该导致潜在的悬挂引用,这可能是Niall代码的情况。但是对于在C ++ 03中合法的东西仍然令人费解。
#include <iostream>
#include <functional>
struct A {
A() =default;
A(A const& a)=default;
A& operator=(A const& a)=default;
A(A &&) = delete; // not movable
A& operator=(A &&) = delete; // not movable
~A()=default;
int n;
};
A foo(void) {
A a;
a.n=5;
std::cout<<"&a="<<&a<<std::endl;
return std::cref(a); // A(A const&)
// ~A()
}
int main(void) {
A b; // A()
std::cout<<"&b="<<&b<<std::endl;
A const& const_ref_to_temp=foo(); // OK in C++
b= const_ref_to_temp; //A=A const& [OK]
std::cout<< b.n<<std::endl;
return 0;
}