2015-10-04 2 views
-1

Я проверяю тайминги на простой код, и я не вижу разницы. В первом блоке он действует, как только передается указатель, в случае 2 и 3 он действует как копирование его по значению не по ссылке, а всей структуре. редактировать ::: структура:Передача структуры функции C++ (эффективность)

struct e{ 
    vector<int> a; 
}; 

Этот код занимает 0 сек:

void ola(e &a) 
{ 
    a.a[0] = 1; 
    a.a[9999] = 1; 
} 

int main() 
{ 
    e *a; 
    a->a.resize(10000000, 0); 
    a->a[0] = 2; 
    a->a[99999] = 2; 
    ola(*a); 
    cout << a->a[0] << " . " << a->a[99999] << endl; 
    letras.resize('z' - 'a' + 1); 
    string entrada; 
} 

Это один занимает 0,15 сек:

void ola(e &a) 
{ 
    a.a[0] = 1; 
    a.a[9999] = 1; 
} 

int main() 
{ 
    e a; 
    a.a.resize(10000000, 0); 
    a.a[0] = 2; 
    a.a[99999] = 2; 
    ola(a); 
    cout << a.a[0] << " . " << a.a[99999] << endl; 
    letras.resize('z' - 'a' + 1); 
    string entrada; 
} 

Но не должно быть никакой разницы. Может быть, это потому, что в ассемблере он должен скопировать все значения структуры при прохождении его, поэтому я попытался это одно:

void ola(e *a) 
{ 
    a->a[0] = 1; 
    a->a[9999] = 1; 
} 

int main() 
{ 
    e a; 
    e* b; 
    a.a.resize(10000000, 0); 
    b = &a; 
    a.a[0] = 2; 
    a.a[99999] = 2; 
    ola(b); 
    cout << a.a[0] << " . " << a.a[99999] << endl; 
    letras.resize('z' - 'a' + 1); 
    string entrada; 
} 

На последнем я прошел только указатель на а, и он принимает 0,15sec тоже. Почему я вижу эту разницу?

+2

1. В первом кодовом блоке 'a' неинициализирован, но вы его разыскиваете. 2. Если вы измеряете что-то как 0 секунд, вы делаете это неправильно. – MooseBoys

+0

0 секунд означает, что это так быстро, что он говорит 0, может быть, это 0,005 с, добавлено struct info @MooseBoys –

+1

Общий совет в таких проблемах заключается в том, что вам следует сравнить ассемблер, сгенерированный вашим компилятором. Для gcc вы можете использовать для этого флаг компиляции -S. – robal

ответ

2

Правильная идея. Профилируйте свой код и проверьте свои предположения, но убедитесь, что код действительно соответствует вашим ожиданиям, и профилирование является точным.

Первая точка: векторы не всегда передаются по ссылке. Компилятор сделает все возможное, чтобы пройти по ссылке, elide или вытащить любой из нескольких подобных трюков, потому что это меньше работает, но когда он не может, вектор будет скопирован.

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

Я проигнорирую тот факт, что случай 1 не работает из-за неинициализированного указателя, который отправляет его в поездку на неопределенную территорию. Это просто бокс-шоу.

Случай 1:

void ola(e &a) 

a передается по ссылке, практически и буквально здесь. Данные не будут копироваться, кроме адреса.

ola(*a); 

a разыменовывается, чтобы удовлетворить требования для ссылки, поэтому мы используем значение в a. Тот факт, что a является указателем, теперь не имеет значения. ola получает ссылку.

Случай 2:

void ola(e &a) 

Идентичные прототип. Также передается по ссылке. Данные не будут копироваться, кроме адреса.

ola(a); 

a передается путем ссылки.

Случай 3:

void ola(e *a) 

Прошёл по ссылке снова, но на этот раз ссылка является указателем. Данные не будут копироваться, кроме адреса.

ola(b); 

b является указателем на a и ola принимает указатель. Никакой работы не требуется. a передается по ссылке.

Чтобы передать по значению, О.П. бы написать:

void ola(e a) 

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

+0

спасибо, что это помогло мне понять, что я сделал –

0

Первая программа, вероятно, сработает, прежде чем делать что-либо полезное. a указывает на недопустимое местоположение в памяти. Оно должно быть:

e *a = new e(); 
a->a.resize(10000000, 0); 
+0

это не сбой, и это дало мне правильный ответ, но, возможно, вы правы, почему же нужно разобрать конструкцию как указатель, чем проанализировать ее foo (struct a)? во втором случае он должен занимать больше времени, поскольку он должен копировать все элементы. –

+1

Не используется копирование. Во всех случаях значение передается через ref или ptr. Только время, которое требуется, - это выделить вектор. –

+0

Я провел тест, анализируя его без указателя, разобрав его по значению и потребовалось то же самое время:/ –

1

В первом блоке вы используете указатель (), который не инициализирован перед использованием. Я подозреваю, что вы забыли часть кода в своем посте.

Кроме того, неясно, что вы хотите сделать точно и что вы пытаетесь сделать вовремя?

Смежные вопросы