ссылка на статический член данных - PullRequest
0 голосов
/ 28 июня 2018

Я читал о привязке ссылки к члену статических данных или получении его адреса, если (и только если) у него есть определение вне класса (https://isocpp.org/wiki/faq/classes-and-objects#in-class-constant).

И когда я попытался протестировать пример (см. Ниже), я заметил, что он работает в Visual Studio 2017 (без ошибок, как ожидалось).

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

#include <iostream>
using namespace std;

class AE {  
public:
    static const int c6 = 7;
    static const int c7 = 31;
};

const int AE::c7; // definition
void byref(const int& a);


int main(int argc, char* argv[])
{   
    byref(AE::c6); // error: c6 not an lvalue
    byref(AE::c7); // ok
    const int* p1 = &AE::c6; // error: c6 not an lvalue
    const int* p2 = &AE::c7; // ok

    std::cout << "p1 " << *p1 << "\n";
    std::cout << "p2 " << *p2 << "\n";
    return 0;
}

void byref(const int & a)
{
    std::cout << a << "\n";
}

Игнорирование компилятора Microsoft на данный момент ...

При компиляции этой программы я получил undefined reference to AE::c6, который с помощью небольшого трюка, найденного в стеке, изменив его на byref(+AE::c6);, разрешит его.

Но для другой строки const int* p1 = &AE::c6;, как показано в комментарии, говорится, что это приведет к ошибке, которая не соответствует действительности (она компилируется и работает нормально).

Итак, у меня есть 2 вопроса:

  1. Какая унарная + роль здесь?
  2. Почему компилятор проигнорировал ошибку const int* p1 = &AE::c6;, что не так, как я ожидал?

1 Ответ

0 голосов
/ 28 июня 2018

Для вашего первого вопроса добавление + перед именем константы меняет значение с константы на выражение. Результат выражения сохраняется во временной переменной без имени, и ссылка на эту временную переменную передается в byref. Без + ссылка делается непосредственно на константу, которая требует, чтобы константа имела определение где-то в программе.

По второму вопросу компилятор не будет выдавать диагностику во время компиляции, потому что одно определение для AE::c6 может присутствовать в другом исходном файле. Компоновщик выдаст ошибку, если не найдет определение.

Стандарт языка [class.static.data] гласит: «Должно быть ровно одно определение статического члена данных, который используется в программе (6.2); нет требуется диагностика. "Таким образом, отсутствие определения или наличие более одного является нарушением, но оно не требуется сообщать. В первом случае компилятор / компоновщик может создать определение для использования, а во втором компоновщик просто выберет одно из доступных определений.

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