Правила псевдонимов в C ++ - PullRequest
21 голосов
/ 12 июня 2011

Просто интересно, не подтвердит ли кто-нибудь несколько правил наложения имен для меня.

Я знаю, что псевдонимы (т.е. проблемы с загрузкой) могут привести к тому, что следующий тип кода будет неоптимальным, поскольку мы не можем предположить, что x, y, z не перекрывается:

// case 1:
void plus(size_t n, double *x, double *y, double *z)
{
    for (size_t i = 0; i != n; ++i)
        z[i] = x[i] + y[i];
} 

Я знаю, что есть ключевое слово C __restrict, которое намекает компилятору, что он не должен учитывать перекрывающийся регистр, и, следовательно, потенциально генерирует лучший код:

// case 2:
void plus(size_t n, double *__restrict x, double *__restrict y, double *__restrict z)
{ // as above... }

Но как псевдонимы работают с кодом стиля C ++, где мы будем иметь дело с объектами-контейнерами, передаваемыми по ссылке, а не с подобными C-образцами, приведенными выше, с необработанными указателями ??

Например, я предполагаю, что были бы проблемы с наложением, если бы мы сделали следующее:

// case 3:
void plus(std::vector<double> &x, std::vector<double> &y, std::vector<double> &z)
{ // similar to above... }

А если перейти к менее тривиальному примеру, имеет ли какое-то значение, если базовые типы данных в контейнерах отличаются? На уровне реализации большинство контейнеров динамически управляют хранилищем с помощью указателей, поэтому мне не ясно, как компилятор может гарантировать, что следующее не будет псевдонимом:

// case 4:
void foo(std::vector<mytype1> &x, std::vector<mytype2> &y)
{ // interwoven operations on x, y... }

Я не пытаюсь микрооптимизировать, но мне интересно, лучше ли сейчас передавать ограниченные указатели на контейнеры, а не ссылки.

РЕДАКТИРОВАТЬ: Чтобы прояснить некоторые термины, как указано: restrict является ключевым словом C99. В различных компиляторах также есть __restrict и __restrict__, но все они делают одно и то же.

Ответы [ 2 ]

7 голосов
/ 12 июня 2011

В соответствии с правилом строгого псевдонима вам не разрешено создавать псевдоним одной и той же памяти с указателями на разные типы (кроме char* и друзей), поэтому случай 4 может применяться только в том случае, еслиТипы были char*.

Случай 3, хотя и не сильно отличается от случая 1, поскольку ссылки реализованы в виде указателей на всех известных мне компиляторах, хотя стандарт не требует этого, и реализациясвободно придумывать что-то еще.

4 голосов
/ 12 июня 2011

Это совсем не относится к C ++. Рассмотрим этот бит C99:

struct vector {
    double* data;
    size_t n;
};

void
plus(struct vector* restrict x, struct vector* restrict y, struct vector* restrict z)
{
    // same deal as ever
}

Здесь restrict очень мало нас покупает: x->data, y->data и z->data - все double* и допускаются к псевдониму. Это похоже на случай 1, даже при использовании restrict.

Если бы в C ++ было ключевое слово restrict (или при использовании расширения), лучше всего было бы сделать plus(vecA.size(), &vecA[0], &vecB[0], &vecB[0]), используя тот же plus, что и в случае 2. И на самом деле это можно сделать это прямо сейчас, используя интерфейс в стиле C89 без restrict, но использующий ключевое слово под обложками.

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