You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++默认返回采用移动还是拷贝语义?C++17返回是否优先移动?

Great question, especially coming from C# where value type semantics work a bit differently! Let’s unpack this clearly, covering both built-in types like int and your user-defined type scenario.

C++ Return Semantics: Core Basics

First, a key point: C++ doesn’t default strictly to either move or copy semantics for returns—instead, it prioritizes copy elision (a compiler optimization that skips creating temporary objects entirely) above all else. When copy elision isn’t possible, C++11 and later will prefer move semantics if a valid move constructor is available; otherwise, it falls back to copy semantics.

Copy elision comes in two common flavors:

  • Return Value Optimization (RVO): Applies to unnamed temporaries (e.g., return MyType();)
  • Named Return Value Optimization (NRVO): Applies to named local variables (e.g., MyType obj; return obj;)

Before C17, copy elision was an optional optimization. C17 made copy elision mandatory in specific cases (like returning a local object or a temporary), meaning the compiler has to skip the copy/move—no exceptions.

Your Example: int ReturnSomething() in C++17

Let’s break down your code snippet:

int ReturnSomething(){ 
    int i = 1; 
    return i; 
}

For built-in types like int, there’s no practical difference between move and copy semantics—both just copy the raw bytes of the value directly. But even more importantly, C++17’s mandatory copy elision applies here. The compiler will initialize the return value directly in the caller’s memory space, skipping any "move" or "copy" of i entirely. There’s no temporary object created; i’s value is constructed right where it needs to be in the caller’s context.

User-Defined Types with Explicit Move Constructors

Now, what about a custom type where you’ve explicitly defined a move constructor? Let’s use this example:

class MyType {
public:
    MyType() = default;
    MyType(const MyType&) { /* Copy constructor logic */ }
    MyType(MyType&&) noexcept { /* Explicit move constructor logic */ }
};

MyType ReturnCustomType() {
    MyType obj;
    return obj;
}
  • If NRVO is possible: The compiler will still prioritize copy elision, constructing obj directly in the caller’s return value slot—no move or copy occurs, even though a move constructor exists. This is always the most efficient path.
  • If NRVO isn’t possible: For example, if you return different named objects based on a branch:
    MyType ReturnCustomType(bool flag) {
        MyType obj1;
        MyType obj2;
        return flag ? obj1 : obj2;
    }
    
    Here, NRVO can’t be applied (since the return value could be either obj1 or obj2). In this case, C++ will prefer the move constructor over the copy constructor, since a valid move constructor is available and accessible. The returned object will be moved from whichever local variable is selected.

One caveat: If you explicitly disable copy elision (e.g., with compiler flags like -fno-elide-constructors), then the move will be used instead of copy when possible.


内容的提问来源于stack exchange,提问作者Reousa Asteron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:46:48