Скопируйте Необходимого Конструктора с временным объектом

Наконец блок, как предполагается, выполняется, поймали ли Вы исключение или нет. См. Попытка / Выгода / Наконец пример

11
задан Martin York 1 December 2009 в 15:51
поделиться

2 ответа

Стандартный стек вызовов функций Matlab сам по себе является стеком рабочих пространств. Простое использование функций - это самый простой способ их использования, и функция копирования при записи в Matlab делает это достаточно эффективным. Но, вероятно, вы спрашиваете не об этом.

Между рабочими пространствами и структурами существует естественное соответствие, поскольку одни и те же идентификаторы действительны для имен переменных и полей структуры. По сути, они оба являются сопоставлениями идентификатор => Mxarray.

Вы можете использовать whos и evalin для захвата состояния рабочего пространства в структуру. Используйте вектор ячейки, чтобы создать стек из них. (Структурный массив не будет работать, потому что он требует однородных имен полей.) Стек может храниться в appdata, чтобы предотвратить его появление в самой рабочей области.

Вот функции push и pop для этой техники. к ссылке конструктор копирования класса должны быть доступны. За Например, рассмотрим следующий код:

class A 
{
public:
  A();

private:
  A(const A&);   // private copy ctor
};

A makeA(void);
void foo(const A&);

void bar(void)
{
  foo(A());       // error, copy ctor is not accessible
  foo(makeA());   // error, copy ctor is not accessible

  A a1;
  foo(a1);        // OK, a1 is a lvalue
}

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

Это будет исправлено в C ++ 1x Core Issue 391 .

15
ответ дан 3 December 2019 в 05:58
поделиться

Применимые части стандарта здесь: §8.5.3 / 5, который охватывает инициализацию ссылок, и §3.10 / 6, который сообщает, что такое rvalue, а что lvalue (не всегда очевидно в C ++).

В этом случае выражение инициализации: «N (1)», поэтому вы явно создаете объект, используя функциональную нотацию. Согласно 3.10 / 6, это выражение является значением R.

Затем мы должны пройти через правила в 8.5.3 / 5 по порядку и использовать первое, что применимо. Первая возможность - если выражение представляет собой lvalue или может быть неявно преобразовано в lvalue. Ваше выражение является rvalue, а неявное преобразование в lvalue потребует функции преобразования, которая возвращает ссылку, которой, похоже, не существует в данном случае, поэтому, похоже, это не применимо.

Следующее правило гласит, что ссылка должна быть на const T (что и имеет место здесь). В этом случае выражение представляет собой rvalue типа класса и совместимо по ссылке со ссылкой (т. Е. Ссылка относится к тому же классу или базе класса). Это означает, что пункт внизу страницы 151 (179 из C ++ 2003 PDF), кажется, применим. В этом случае компилятору разрешено либо привязать ссылку непосредственно к объекту, представляющему rvalue, либо создать временную копию rvalue и привязать к этой временной копии.

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

Таким образом, я полагаю , что gcc имеет право выдавать сообщение об ошибке, а остальные технически неправильно принимают код. Я немного упростил ваш код до следующего:

class N {
    public:
        N(int)  {}
    private:
        N(N const&);
};

void plop(N const& data) { }

int main() {
    plop(N(1));
}

При вызове с «--A» (режим строгих ошибок) Comeau выдает следующее сообщение об ошибке:

"plop.cpp", line 12: error: "N::N(const N &)", required for copy that was
          eliminated, is inaccessible
      plop(N(1));
           ^

Аналогично, при вызове с «/ Za» (его «ANSI» соответствующий "режим), VC ++ 9 дает:

plop.cpp
plop.cpp(12) : error C2248: 'N::N' : cannot access private member declared in class 'N'
        plop.cpp(6) : see declaration of 'N::N'
        plop.cpp(2) : see declaration of 'N'
        while checking that elided copy-constructor 'N::N(const N &)' is callable
        plop.cpp(6) : see declaration of 'N::N'
        when converting from 'N' to 'const N &'

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

"plop.cpp", line 12: error: "N::N(const N &)", required for copy that was
          eliminated, is inaccessible
      plop(N(1));
           ^

Аналогичным образом, при вызове с "/ Za" (его "соответствующий ANSI" режим), VC ++ 9 дает:

plop.cpp
plop.cpp(12) : error C2248: 'N::N' : cannot access private member declared in class 'N'
        plop.cpp(6) : see declaration of 'N::N'
        plop.cpp(2) : see declaration of 'N'
        while checking that elided copy-constructor 'N::N(const N &)' is callable
        plop.cpp(6) : see declaration of 'N::N'
        when converting from 'N' to 'const N &'

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

"plop.cpp", line 12: error: "N::N(const N &)", required for copy that was
          eliminated, is inaccessible
      plop(N(1));
           ^

Аналогичным образом, при вызове с "/ Za" (его "соответствующий ANSI" режим) VC ++ 9 дает:

plop.cpp
plop.cpp(12) : error C2248: 'N::N' : cannot access private member declared in class 'N'
        plop.cpp(6) : see declaration of 'N::N'
        plop.cpp(2) : see declaration of 'N'
        while checking that elided copy-constructor 'N::N(const N &)' is callable
        plop.cpp(6) : see declaration of 'N::N'
        when converting from 'N' to 'const N &'

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

5
ответ дан 3 December 2019 в 05:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: