【问题标题】:How can a unique_ptr be returned by value without std::move? [duplicate]如何在没有 std::move 的情况下按值返回 unique_ptr? [复制]
【发布时间】:2014-11-11 03:57:19
【问题描述】:
std::unique_ptr<int> ptr() {
    std::unique_ptr<int> p(new int(3));
    return p;  //  Why doesn't this require explicit move using std::move?
}  // Why didn't the data pointed to by 'p' is not destroyed here though p is not moved?

int main() {
    std::unique_ptr<int> a = ptr();  // Why doesn't this require std::move? 
    std::cout << *a; // Prints 3.
}

在上面的代码中,函数ptr()返回一个p的副本。当p 超出范围时,应该删除数据“3”。但是代码如何在没有任何访问冲突的情况下工作?

【问题讨论】:

  • 它实际上使用了std::unique_ptr&lt;&gt;move constructor
  • 请参阅this related question。无论谁把它作为“未定义行为”的欺骗而结束,都需要喝杯咖啡。
  • 这叫copy elision
  • @MattMcNabb 仍然必须有一个可行的复制/移动复制构造函数重载。

标签: c++ c++11 move-semantics copy-elision


【解决方案1】:

这在 C++11 标准中规定,§ 12.8/32

当满足或将满足省略复制操作的条件时 遇到源对象是函数参数这一事实, 并且要复制的对象由左值指定,overload 首先执行为副本选择构造函数的分辨率 就好像对象是由右值指定的一样....

(强调我的)。用简单的英语来说,这意味着当涉及到重载决议时,左值p 可以被视为rvalue,因为它是复制省略 的候选者。这反过来意味着移动构造函数在重载决议时被拾取(实际上,移动副本可能无论如何都被省略了。)

【讨论】:

    【解决方案2】:

    因为return 的某些表达式,例如局部自动变量,被明确定义为返回一个moved 对象,如果移动运算符可用的话。

    所以:

    return p;
    

    或多或少类似于:

    return std::move(p);
    

    但请注意,这不适用于例如全局变量。

    std::unique_ptr<int> g(new int(3));
    std::unique_ptr<int> ptr() {
        return g;  //  error!!!
    }
    

    【讨论】:

    • 这通常不是真的。它仅适用于p 符合复制省略条件的情况。
    • @MattMcNabb:每个 return 表达式都有值。还有其他几个地方。
    • @rodrigo 不,没那么简单。复制省略的条件比这更复杂(不幸的是!)
    • @rodrigo " 在具有类返回类型的函数的返回语句中,当表达式是具有与函数返回类型相同的 cv-unqualified 类型,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作。
    • 即你的答案仍然是错误的。
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2020-06-15
    • 2020-10-19
    • 2012-03-20
    • 2013-08-18
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多