Это хорошая практика для передачи объекта структуры в качестве параметра функции в C ++? - PullRequest
8 голосов
/ 28 апреля 2010

Я попробовал пример вживую ниже:

typedef struct point
{
    int x;
    int y;
} point;

void cp(point p)
{
    cout<<p.x<<endl;
    cout<<p.y<<endl;
}

int main()
{
    point p1;
    p1.x=1;
    p1.y=2;
    cp(p1);
}

Результат, который распечатан:

1
2

что я и ожидал. Мой вопрос: получает ли параметр p полную копию объекта p1? Если так, то мне интересно, если это хорошая практика? (Я предполагал, что когда структура станет больше по размеру, это приведет к большим затратам на копирование).

Ответы [ 6 ]

18 голосов
/ 28 апреля 2010

Да, в этом нет ничего плохого, и да, p является полной копией p1. Я бы не назвал struct с двумя int большими, но если struct становится большим и если вам не нужно изменять его в теле функции, вы можете рассмотреть возможность передачи его по константной ссылке:

void cp(const point& p)
{
    // ...
}
8 голосов
/ 28 апреля 2010

В передаче параметров в качестве параметров нет ничего плохого. Все передается по значению в C ++, поэтому полная копия действительно сделана.

Структура, которую вы дали в своем примере, мала, так что, вероятно, это не проблема, если вы передадите ее по значению. Но если вы работаете с большими структурами данных, вы можете передать их по ссылке.

Однако будьте осторожны, если передать по ссылке, это означает, что если вы измените структуру внутри вашей функции, ваша исходная структура будет изменена. Обязательно используйте ключевое слово const в каждом случае, когда вы не изменяете структуру. Это даст вам немедленную информацию о том, изменили ли ваши функции информацию или нет.

Ваш пример может быть изменен для работы со ссылками следующим образом:

typedef struct point
{
    int x;
    int y;
} point;

void cp(const point& p) // You can know that cp doesn't modify your struct
{
    cout<<p.x<<endl;
    cout<<p.y<<endl;
}

void mod_point(point& p) // You can know that mod_points modifies your struct
{
    p.x += 1;
    p.y += 1;
}

int main()
{
    point p1;
    p1.x=1;
    p1.y=2;
    cp(p1);
    mod_point(p1);
    cp(p1); // will output 2 and 3
}
5 голосов
/ 28 апреля 2010

Прежде чем я дам ответ на ваш вопрос (вы найдете его в конце этого поста), вот краткое описание возможностей, которые вы имеете для передачи аргументов в функцию:


1.Объекты копирования (передача по значению):

void cp(point p);

Это передача по значению.Временный объект point создается и копируется из любого объекта point, который вы передаете в cp.Как только выполнение покидает функцию cp, временный объект уничтожается.

Обратите внимание, что поскольку функция работает с копией всего, что было передано функции, вы можете изменить этот локальный объект point столько, сколькоВы хотите, оригинальный объект звонящего не будет затронут.Невозможно изменить это поведение с помощью параметров передачи по значению.


2.Ссылки на объекты (передача по ссылке):

void cp(point& p);

Это передача по ссылке.Фактический объект, переданный функции, доступен (и потенциально может быть изменен) внутри функции.Если вы не хотите, чтобы функция могла изменять переданный объект, объявите параметр как const point&:

void cp(const point& p);

3.Указатели на объекты (передача по ссылке):

void cp(point* p);

Это также передача по ссылке, с небольшими различиями.Одно заметное отличие состоит в том, что вы можете передать нулевой указатель на функцию.Это невозможно с ссылками, поскольку ссылки должны быть инициализированными и не могут быть переустановлены впоследствии.- Как и в случае со ссылками, если вы хотите запретить cp изменять переданный point, объявите его как const:

void cp(const point* p);

Ответ на свой вопрос:

Параметры передачи по значению не являются плохими по своей природе.Конечно, существуют типы, для которых копирование является дорогостоящим (например, очень большие или сложные объекты), или когда оно имеет определенные побочные эффекты (например, с std::auto_ptr).В этих случаях вы должны быть осторожны.В противном случае это просто еще одна особенность C ++, которая имеет вполне разумное применение.

0 голосов
/ 28 апреля 2010

Смотрите возможности, чтобы избежать передачи объектов по значению. Объект не просто «копируется», а создается с помощью копирования. Таким образом, это включает в себя вызов конструктора копирования и цепочки конструкторов копирования, если ваш объект составлен или образован из большего количества объектов. Передайте по ссылке, если это возможно.

void cp (point & p const) const {

    cout << p.x << endl;
    cout << p.y << endl;

}

0 голосов
/ 28 апреля 2010

В вашем случае точечная структура передается «по значению», что означает, что вся структура скопирована. Для больших типов данных это действительно может быть медленным.

Вы можете рассмотреть возможность передачи объекта по ссылке

void cp(point& p) // p may be altered!

или быть постоянной ссылкой

void cp(const point& p) // p may not be altered!
0 голосов
/ 28 апреля 2010
void cp(point p){
}

получает его по значению

void cp(point *p){
}

получает по ссылке

Как и любая другая переменная данных.

В Java сценарий другой. Проходящие объекты всегда идут по ссылке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...