C++ 클래스 포인터 반환 - C++ keullaeseu pointeo banhwan

C++

객체 포인터와 동적 메모리 할당 및 반환, this포인터

객체 포인터와 동적 메모리 할당 및 반환, this포인터에 대해서 작성하겠습니다.

객체 포인터는 객체의 멤버 변수를 읽고 값을 쓰거나 멤버 함수를 호출 가능합니다.

첫 번째 빨간 박스를 보시면

클래스를 생성하고 포인터변수로 선언합니다.

그리고 위에서 선언한 객체의 주소를 포인터p가 가리키도록 합니다.

그리고 그 클래스에 안의 멤버함수에 대한 접근은

두 번째 빨간 박스와 같이 두가지 방법이 있는데

->는 포인터로 접근하는 방법이고

.은 객체이름으로 멤버를 접근하는 방법입니다. 

객체 배열입니다. 선언하는 방식은 첫 번째 박스처럼 선언하시면 됩니다.

그리고 일반 배열처럼 인덱스로 그 클래스의 멤버함수에 대해 접근이 가능합니다.

그리고 객체 배열 선언문은 기본생성자를 호출합니다.

[3]으로 생성하면 3개의 객체를 생성하고 객체마다

기본 생성자를 호출합니다.

네 번째 빨간 박스를 보시면 클래스를 포인터로 선언하고

포인터가 배열을 가리키도록 합니다.

그리고 for문안을 보시면 마지막 줄에 p++가 있는데 

이것은 다음 객체 주소로 갈수 있도록 증가를 시켜주는 역할을 합니다.

함수가 종료하면 선언된 배열도 소멸됩니다. 

또 모든 원소객체도 소멸됩니다.

그리고 객체마다 소멸자를 호출하게 됩니다.

C++에서 동적 메모리 할당 및 반환에는 

두가지 연산자가 존재합니다. new연산자와 delete연산자가 있습니다.

new연산자는 데이터 크기만큼 메모리를 할당 받습니다. 그리고 주소를 리턴합니다.

ex)를 보시면 int *pint = new int 는 정수형 타입으로 할당을 받겠다는 의미를 가집니다.

delete연산자는 할당받은 메모리를 반환시켜주는 역할을 합니다.

ex)에서 delete pint 는 정수형 타입으로 할당받은 메모리를 모두 반환시켜준다는 의미를 가지고 있습니다.

위와 같은 예시처럼 쓰게 됩니다.

정수형 타입으로 할당을 받고 

포인터p에 5를 넣습니다. 그리고

새로운 변수 n에 포인터p의 값을 넣습니다.

this포인터는 객체 자신에 대한 포인터이고

클래스의 멤버 함수 내에서만 사용가능합니다. 

그리고 this포인터를 써야하는 경우가 2가지가 있는데 

첫 번째는

이와 같이 멤버 변수와 매개 변수의 이름이 동일할때 씁니다.

그 이유는 radius라는 변수가 모두 매개변수를 지칭하게 되어 멤버 변수에 값을 쓰는 목적이 왜곡됩니다.

그래서 this로 멤버 변수와 매개 변수를 구분해줍니다.

두 번째는 객체의 멤버함수에서 객체 자신의 주솔르 리턴 할 때 입니다,

연산자 중복에서 많이 쓰이는 경우입니다.

this포인터에는 제약조건이 있는데

멤버 함수에서만 작성을 해야합니다.

그리고 

멤버 함수여도 정적 멤버 함수에서는 사용 불가합니다. 

그 이유는

정적 멤버 함수는 객체가 생성되기전에 호출될 수 있다.

그래서 정적 멤버함수가 실행되는 시점에서 

현재 객체라는 것은 존재하지 않게 되기 때문입니다.

앞서 'C++기본 프로그램의 기본 요소와 화면 출력'에서 설명했듯이

string클래스를 이용한 문자열 사용입니다. 

str은 아무것도 초기화하지 않았기 때문에

빈 문자열이 출력이 되고

adress는 괄호안에 초기화된 문자열을 출력해줍니다.

copyAdress는 adress의 변수안에 있는 문자열을 

복사해서 출력하는 역할을 합니다.

  1. std::string::data함수를 사용하여 C++의 함수에서 포인터 반환
  2. &variable 주소 연산자을 사용하여 C++의 함수에서 포인터 반환

이 기사에서는 C++의 함수에서 포인터를 반환하는 방법에 대한 몇 가지 방법을 설명합니다.

std::string::data함수를 사용하여 C++의 함수에서 포인터 반환

함수 반환 유형은 일반적으로 값, 참조 또는 포인터의 세 가지 범주로 나뉩니다. 그들 모두는 최적의 사용 사례를 가지고 있습니다.
대부분의 성능에 도달합니다. 일반적으로 함수에서 포인터를 반환하는 것은 C 언어에서 더 일반적입니다. C++는 객체를 복사하지 않고 함수를 사용하여 전달하고 반환하기위한 참조 인보다 웅변적인 개념을 제공하기 때문입니다. 포인터를 더 잘 활용할 수있는 시나리오가 있지만 다른 데이터 구조에 대한 포인터 값을 반환하는 방법에 대한 몇 가지 예를 보여줍니다.

다음 예제 코드에서는std::string에 대한 참조를 사용하고 기본 데이터 유형 인char*를 반환하는 함수를 구현합니다. std::string클래스는 연속적으로 저장된char시퀀스를 포함하는 데 사용됩니다. data()내장 함수를 사용하여 시퀀스의 첫 번째 문자에 대한 포인터를 검색하고return문 다음에 전달할 수 있습니다. 마지막으로 필요에 따라 반환 된 포인터를 사용하여char배열에 대해 작업 할 수 있습니다.

#include <iostream>
#include <algorithm>
#include <iterator>

using std::cout; using std::endl;
using std::string; using std::reverse;

char *reverseString(string &s) {
    reverse(s.begin(), s.end());
    return s.data();
}

int main() {
    string str = "This string shall be reversed";

    cout << str << endl;
    cout << reverseString(str) << endl;

    return EXIT_SUCCESS;
}

출력:

This string shall be reversed
desrever eb llahs gnirts sihT

&variable 주소 연산자을 사용하여 C++의 함수에서 포인터 반환

연산자의&주소는 C 언어로 다시 뿌리를 내리고 C++는 동일한 의미를 사용하여 그 뒤에 오는 객체의 메모리 주소를 사용합니다. 그러나operator&가 오버로드되면 동작이 약간 다릅니다 (페이지 참조). 이 경우 배열을 인수 중 하나로 취하고 동일한 배열에 대한 포인터를 반환하는 함수를 보여줍니다. 배열 객체에 대한 포인터는 배열의 첫 번째 요소에 대한 포인터와 동일하므로 주어진 배열의 주소를 반환하기 위해&arr[0]표기법을 사용할 수 있습니다.

#include <iostream>
#include <algorithm>
#include <iterator>

using std::cout; using std::endl;
using std::string; using std::reverse;

int *subtructArray(int arr[], size_t size, int subtrahend)
{
    for (size_t i = 0; i < size; ++i) {
        arr[i] -= subtrahend;
    }
    return &arr[0];
}

int main() {

    int c_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int num = 3;

    auto arr_size = sizeof c_array / sizeof c_array[0];
    int *ptr = subtructArray(c_array, arr_size, num);

    cout << "c_array = [ ";
    for (int i = 0; i < arr_size; ++i) {
        cout << ptr[i] << ", ";
    }
    cout << "\b\b ]" << endl;


    return EXIT_SUCCESS;
}

출력:

c_array = [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ]

또는 배열이 함수 블록에서 참조되는 변수 이름 만 사용하여 이전 코드를 다시 작성할 수 있습니다. 함수가int arr[]를 매개 변수로 사용하더라도 컴파일러는 그 아래에있는 배열을 복사하지 않고 포인터를 전달합니다. arr이름을return문에 전달하면 포인터가 반환됩니다.

#include <iostream>
#include <algorithm>
#include <iterator>

using std::cout; using std::endl;
using std::string; using std::reverse;

int *subtructArray(int arr[], size_t size, int subtrahend)
{
    for (size_t i = 0; i < size; ++i) {
        arr[i] -= subtrahend;
    }
    return arr;
}

int main() {

    int c_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int num = 3;

    auto arr_size = sizeof c_array / sizeof c_array[0];
    int *ptr = subtructArray(c_array, arr_size, num);

    cout << "c_array = [ ";
    for (int i = 0; i < arr_size; ++i) {
        cout << ptr[i] << ", ";
    }
    cout << "\b\b ]" << endl;


    return EXIT_SUCCESS;
}

출력:

c_array = [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ]