>

나는 다음 코드로 장난을 쳤으며 Visual Studio 2017 응용 프로그램과 두 개의 다른 온라인 컴파일러를 사용하여 다른 결과를 얻었습니다. 릴리스 모드에서 Visual Studio는 두 경우 모두 복사/이동을 제거하지만 두 온라인 컴파일러는 괄호로 묶지 않은 return 문의 경우에만 수행합니다. 내 질문은 : 누가 옳고 더 중요한 것은 기본 규칙이 무엇인가입니다. ( decltype(auto) 와 함께 괄호를 사용할 수 있다는 것을 알고 있습니다. 통사론. 그러나 이것은 현재 사용 사례가 아닙니다.)

예제 코드 :

#include <iostream>
#include <cstdio>
struct Foo
{
    Foo() { std::cout << "default constructor" << std::endl; }
    Foo(const Foo& rhs) { std::cout << "copy constructor" << std::endl; }
    Foo(Foo&& rhs) { std::cout << "move constructor" << std::endl; }
    Foo& operator=(const Foo& rhs) { std::cout << "copy assignment" << std::endl; return *this; }
    Foo& operator=(Foo&& rhs) { std::cout << "move assignment" << std::endl; return *this; }
};
Foo foo_normal()
{
    Foo a{};
    return a;
}
Foo foo_parentheses()
{
    Foo a{};
    return (a);
}
int main()
{
    auto a = foo_normal();
    auto b = foo_parentheses();
    std::getchar();
}

온라인 컴파일러 1 : http://cpp.sh/75bux

온라인 컴파일러 2 : http://coliru.stacked-crooked.com/a/c266852b9e1712f3

>

릴리스 모드에서 Visual Studio의 출력은 다음과 같습니다.

default constructor
default constructor

다른 두 컴파일러에서 결과는 다음과 같습니다 :

default constructor
default constructor
move constructor


  • 답변 # 1

    GCC가 옳다.

    [class.copy.elision] 단락 1에 따르면 :

    와이즈 비즈 와이즈 비즈  표현식비 휘발성 자동 객체의 이름인 경우 (<매개 변수 또는<함수 반환 유형과 동일한 유형 (cv-qualification 무시)으로핸들러([except.handle])의 em-exception-declaration은 복사/이동 작업이 될 수 있습니다. 자동 객체를 함수 호출의 반환 객체로 직접 구성하여 생략

      

    ...

      

    This elision of copy/move operations, calledcopy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

      in a 에서 판화 된 표현  문이 복사 제거 기준에 맞지 않습니다.

      실제로 CWG 1597이 해결 될 때까지 return 에서 괄호로 묶인 id- 표현  명령문은 이동을 수행하기위한 rvalue로 간주 될 수 없습니다.

  • 답변 # 2

    이 표준의 관련 인용문입니다 :

    와이즈 비즈

    따라서 요구 사항은

    <올>

    반환 진술서

    함수에서

    클래스 리턴 유형 사용

    표현식이 비 휘발성 자동 객체의 이름 인 경우 (함수 매개 변수 또는 핸들러의 예외 선언 ([except.handle])에 의해 도입 된 변수 제외)

    함수 반환 타입과 같은 타입 (cv-qualification 무시)

    요구 사항 1, 2, 3 및 5는 충족되었지만 주장 4는 그렇지 않다고 주장한다. 와이즈 비즈  객체의 이름이 아닙니다. 따라서 주어진 코드에 대해서는 복사 제거가 적용되지 않습니다. 이동 생성자는 부작용이 있으므로 as-if 규칙에 따라 제거 할 수 없습니다.

    그러므로 gcc가 옳고 여기에 비주얼 스튜디오 (및 클랜)가 잘못되었습니다.

    return

관련 자료

  • 이전 regex - ng 빌드는 regExp로 인해 오류를 발생시킵니다
  • 다음 ios - 플레이어 앱으로 돌아간 후 소리가 들리지 않습니다