«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
04-25 03:42
관리 메뉴

lancelot.com

Temporary 본문

프로그래밍

Temporary

lancelot50 2022. 8. 3. 21:41
  • temporary
    • named object VS unnamed object
      • named object
        • Point pt(1,2);
        • 자신을 선언한 블록을 벗어날 때 파괴
      • unnamed object
        • Point(1,2);
        • 자신을 선언한 문장의 끝에서 파괴
        • 임시객체(temporary)
#include<iostream>

class Point
{
	int x, y;
public :
	Point(int x, int y) : x(x), y(y) { std::cout << "Point(int, int)" << std::endl; }
	~Point() { std::cout << "~Point()" << std::endl; }
};

int main()
{
	Point pt(1, 2);	// named object : 수명이 자신을 선언한 블록
	Point(1, 2);	// unnamed object : 수명이 statement - 임시객체(temporary)

	std::cout << "-----------------" << std::endl;
}

 

  • temporary 의 특징
    • 등호 왼쪽에 놓을 수 없다
      • temporary 는 rvalue이다
      • 상수는 아니고, 멤버함수를 호출 할 수 있다.
        • temporary proxy 참고.
    • 주소 연산자로 주소를 구할 수 없다
      • 생성자에서 "this"를 사용할 수는 있다.
    • temporary 와 reference
Point& r = Point(1,2);		// error
const Point& r = Point(1,2);	// ok
Point&& r = Point(1,2);		// ok, C++11
#include<iostream>

class Point
{
public:
	int x, y;

	Point(int x, int y) : x(x), y(y) { std::cout << "Point(int, int)" << std::endl; }
	void set(int a, int b) { x = a; y = b; }
};

int main()
{
	Point pt(1, 2);

	pt.x = 10;
	Point(1, 2).x = 10;		// error : temporary는 등호의 왼쪽에 놓을 수 없다. rvalue 이다
	Point(1, 2).set(10, 20);// ok : 상수는 아니고 멤버함수를 호출할 수 있다. temporary proxy 참조.

	Point* p1 = &pt;		// ok
	Point* p2 = &Point(1, 2);// error : 주소연산자로 주소를 구할 수 없다 - 생성자에서 this를 사용할 수는 있다

	Point& r1 = pt;			// ok
	Point& r2 = Point(1, 2);// error : lvalue reference 에 rvalue를 담을 수 없다

	const Point& r3 = Point(1, 2);	// ok : 상수포인터에는 가능
}

 

  • temporary 와 함수 인자
    • 객체를 함수 인자로만 사용한다면
      • temporary 로 전달하는게 효율적일 수 있다
      • 이 경우, 함수 인자는 반드시 "const Point&"로 받아야한다
      • foo({1,2}) 로도 전달 가능.
#include<iostream>

class Point
{
	int x, y;
public :
	Point(int x, int y) : x(x), y(y) { std::cout << "Point(int, int)" << std::endl; }
	~Point() { std::cout << "~Point()" << std::endl; }
};

void foo(const Point& pt)	{ std::cout << "foo" << std::endl; }

int main()
{
//	Point pt(1, 2);
//	foo(pt);

	foo(Point(1, 2));	// foo(Point{1,2});	C++11

	foo({ 1,2 });		// foo(Point{1,2});

	std::cout << "-----------------" << std::endl;
}

 

  • string 과 함수인자
#include<string>
#include<string_view>

void foo(const std::string& s){ }
void goo(std::string_view s) { }	// C++17 이후

int main()
{
	foo("Practive make perfect");// string("Practive make perfect") 의 임시객체를 만들어서 복사 - 문자열의 복사본도 힙에 생성 (단 짧은경우 SSO 적용)
	goo("Practive make perfect");// string_view 는 주소와 길이만 가지고 있으므로 복사본을 생성하지 않아서 더 빠르다
}

string 과 string_view

 

  • temporary 와 함수 반환값
    • return by value : 리턴용 임시객체가 반환
    • return by reference : 리턴용 임시객체가 생성되지 않는다.

 

  • temporary 와 캐스팅
    • 사용자정의 타입을 값으로 캐스팅하면 temporary 가 생성된다.
#include<iostream>

struct Base
{
	int value = 10;
};

struct Derived : public Base
{
	int value = 20;
};

int main()
{
	Derived d;
	std::cout << d.value << std::endl;	// 20
	std::cout << static_cast<Base&>(d).value << std::endl;	// 10
	std::cout << static_cast<Base>(d).value << std::endl;	// 10

	static_cast<Base&>(d).value = 100; // ok
	static_cast<Base>(d).value = 100; // error 사용자정의 타입을 값으로 캐스팅하면 temporary가 생성된다.
}

temporary and casting

 

  • temporary
    • 사용자가 명시적으로 만드는 경우
      • 함수 인자로 객체를 전달할 때
      foo( Point(1,2) );
    • 컴파일러에 의해 생성되는 경우
        • 함수인자로 객체가 아닌 생성자를 전달할 때
      void foo(const std::string& s) {}
      foo("Practive make perfect");
      • 함수가 값으로 객체를 반환할 때
      • Point f3() { return pt; }
      • 객체를 값으로 캐스팅할 때
      • static_cast<Base>(d).value