const 참조 클래스 멤버는 임시 수명을 연장합니까? main() { Sandbox sandbox(string(“four”));

왜 이런가요?

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

다음을 출력하십시오.

정답은:

대신에:

답은 : 4



답변

지역 const 참조 만으로 수명이 연장됩니다.

표준은 이러한 행동을 §8.5.3 / 5, [dcl.init.ref], 참조 선언의 초기화에 관한 섹션에서 지정합니다. 예제의 참조는 생성자의 argument nn바인딩되어 있으며 개체 가 범위를 벗어나면 바인딩되지 않습니다 .

수명 연장은 함수 인수를 통해 전이되지 않습니다. §12.2 / 5 [class.temporary] :

두 번째 컨텍스트는 참조가 임시에 바인딩 될 때입니다. 참조가 바인드 된 임시 또는 임시가 바인드 된 서브 오브젝트에 대한 완전한 오브젝트 인 임시는 아래에 지정된 것을 제외하고 참조의 수명 동안 지속됩니다. 생성자의 ctor-initializer (§12.6.2 [class.base.init])에서 참조 멤버에 대한 임시 바인딩은 생성자가 종료 될 때까지 지속됩니다. 함수 호출 (§5.2.2 [expr.call])에서 참조 매개 변수에 대한 임시 바인딩은 호출을 포함하는 전체 표현식이 완료 될 때까지 지속됩니다.


답변

발생한 일을 설명하는 가장 간단한 방법은 다음과 같습니다.

main ()에서 문자열을 만들어 생성자에 전달했습니다. 이 문자열 인스턴스는 생성자 내에서만 존재했습니다. 생성자 내에서이 인스턴스를 직접 가리 키도록 멤버를 할당했습니다. scope가 생성자를 떠날 때 문자열 인스턴스가 삭제되고 멤버가 더 이상 존재하지 않는 문자열 객체를 가리 켰습니다. Sandbox.member가 범위 외부의 참조를 가리 키도록하면 해당 외부 인스턴스가 범위에 포함되지 않습니다.

원하는 동작을 표시하도록 프로그램을 수정하려면 다음과 같이 변경하십시오.

int main()
{
    string temp = string("four");
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

이제 temp는 생성자 끝이 아닌 main () 끝에서 범위를 벗어납니다. 그러나 이것은 나쁜 습관입니다. 멤버 변수는 인스턴스 외부에 존재하는 변수에 대한 참조가되어서는 안됩니다. 실제로는 해당 변수가 범위를 벗어날 시점을 절대 알 수 없습니다.

내가 권장하는 것은 Sandbox.member를 a로 정의하는 const string member;것입니다 . 이것은 멤버 변수를 임시 매개 변수로 할당하는 대신 임시 매개 변수의 데이터를 멤버 변수에 복사합니다.


답변

기술적으로 말하면,이 프로그램은 실제로 표준 출력 (처음으로 버퍼링 된 스트림)으로 아무것도 출력하지 않아도됩니다.

  • cout << "The answer is: "비트가 발광 할 "The answer is: "버퍼 표준 출력의.

  • 그런 다음 << sandbox.member비트는에 매달려있는 참조를 제공하여 정의되지 않은 동작operator << (ostream &, const std::string &) 을 호출합니다 .

이 때문에 아무 일도 일어나지 않습니다. 프로그램이 정상적으로 작동하거나 stdout을 비우지 않고도 작동이 중단 될 수 있습니다. “응답은 다음과 같습니다.”라는 텍스트가 화면에 나타나지 않습니다.


답변

샌드 박스 생성자가 반환되면 임시 문자열이 범위를 벗어 났고이 문자열이 차지한 스택이 다른 목적으로 회수되었습니다.

일반적으로 참조를 장기적으로 유지해서는 안됩니다. 참조는 인수 또는 로컬 변수에 적합하며 클래스 멤버는 아닙니다.


답변

사라진 것을 말하는 것입니다. 다음은 작동합니다

#include <string>
#include <iostream>

class Sandbox
{

public:
    const string member = " "; //default to whatever is the requirement
    Sandbox(const string& n) : member(n) {}//a copy is made

};

int main()
{
    Sandbox sandbox(string("four"));
    std::cout << "The answer is: " << sandbox.member << std::endl;
    return 0;
}


답변