Ошибка компилятора c2102

The compiler is right, according to ISO C++ § 5.3.1.3:

The result of the unary & operator is a pointer to its operand. The
operand shall be an lvalue or a qualified-id.

In other words, you can take an address of anything that has a name.

Values returned from functions by-value have no name and are often returned via a register. So there is no «address» to speak of as the value is not residing in memory!

One could argue that the compiler could be smarter, detect this and store the value on the stack for the duration of the expression in which the address is used. But that is error-prone (you can «leak» a pointer to outside the expression), and would clearly be an extension of the standard (i.e. not guaranteed to be compatible). So MSVC simply prohibits it.

Entertainingly, the compiler is that smart when it comes to a reference to an rvalue. But there is no such functionality for a pointer to an rvalue.

To answer your question: try to minimize taking addresses of stuff; taking an address of a variable prevents the optimizer from putting it into a register.
But if you have to, return a reference instead:

class a {
private:
    int dummy;
public:
    int get_dummy() const {
        return dummy;
    }
    int& get_dummy() {
        return dummy;
    }
};

int main()
{
    a aa;

    int* me = &(aa.get_dummy());
}

Note that having a const get_dummy() is not strictly needed, but will help the optimizer in rvalue contexts.

The compiler is right, according to ISO C++ § 5.3.1.3:

The result of the unary & operator is a pointer to its operand. The
operand shall be an lvalue or a qualified-id.

In other words, you can take an address of anything that has a name.

Values returned from functions by-value have no name and are often returned via a register. So there is no «address» to speak of as the value is not residing in memory!

One could argue that the compiler could be smarter, detect this and store the value on the stack for the duration of the expression in which the address is used. But that is error-prone (you can «leak» a pointer to outside the expression), and would clearly be an extension of the standard (i.e. not guaranteed to be compatible). So MSVC simply prohibits it.

Entertainingly, the compiler is that smart when it comes to a reference to an rvalue. But there is no such functionality for a pointer to an rvalue.

To answer your question: try to minimize taking addresses of stuff; taking an address of a variable prevents the optimizer from putting it into a register.
But if you have to, return a reference instead:

class a {
private:
    int dummy;
public:
    int get_dummy() const {
        return dummy;
    }
    int& get_dummy() {
        return dummy;
    }
};

int main()
{
    a aa;

    int* me = &(aa.get_dummy());
}

Note that having a const get_dummy() is not strictly needed, but will help the optimizer in rvalue contexts.

Search code, repositories, users, issues, pull requests…

Provide feedback

Saved searches

Use saved searches to filter your results more quickly

Sign up

Вопрос:

Я создаю консольное приложение в С++ с большим количеством меню и подменю. То, как я показываю свое меню, – это цикл do-while. Я создал функцию для отображения цикла меню с тремя параметрами – сначала это целое число, которое относится к количеству опций в меню, второе – функция, отображающая меню, а третья – другая функция, которая выполняет выбор, введенный пользователем.

class Menu {
public:

void displayInitialMenu(){
system("cls");
string menu = "\n\t\tXXXXXXXXX"\
"\n\n Please select from the following:"\
"\n\n 1. XXXXXXX"\
"\n\n 2. XXXXXXX"\
"\n\n 3. Exit\n";
cout << menu << endl;
}



static bool checkOption (int option, int lower, int upper){
if ((option < lower) || (option > upper)){
return false;
} else {
return true;
}
}

static int readOption(int lower, int upper){

int option = 0;
bool validMenuOption = false;

do{
std::cin >> option;
validMenuOption = checkOption(option, lower, upper);

if (!validMenuOption){
std::cout << "\nError: Input must be between " << lower;
std::cout << " and " << upper << "\n" << std::endl;
}
} while (!validMenuOption);

return option;
}
};

Menu menu;

void menuLoop(int numberOfOptions, void (*displayMenu)(), void (*switchStatement)()){
int menuOption = numberOfOptions;
do {
(*displayMenu)();
menuOption = menu.readOption(1, numberOfOptions);
(*switchStatement)();
} while (menuOption != numberOfOptions);
}

static void performSelectionInitialMenu(int option){

switch (option){
case 1:
break;

case 2:
break;

case 3:
break;

default:
break;
}
}

int main()
{
/*
int menuOption = 3;
do {
menu.displayInitialMenu();
menuOption = menu.readOption(1, 3);
performSelectionInitialMenu(menuOption);
} while (menuOption != 3);
*/

menuLoop(3, &menu.displayInitialMenu(), &performSelectionInitialMenu(3));

return 0;
}

Ошибка, которую я получаю, является ошибкой “C2102: ‘&’ требуется l-значение” . Я несколько новичок в программировании, и это первый раз, когда я передаю функцию в качестве параметра. Я делаю эту функцию для устранения кода, который я прокомментировал. Может ли кто-нибудь указать, где я ошибаюсь, и возможное решение. Если нет, я просто использую дубликат кода для каждого меню, которое, как я знаю, плохое программирование.

Лучший ответ:

Вы пытаетесь взять адреса значений, возвращаемых функциями displayInitialMenu и performSelectionInitialMenu, но обе эти функции ничего не возвращают (void). Удалите & перед обеими вызовами, чтобы исправить эту конкретную проблему.

Ответ №1

Обычно вы вызываете его только так:

menuLoop(3, menu.displayInitialMenu, performSelectionInitialMenu);

просто имя, никаких параметров.

Однако performSelectionInitialMenu:

static void performSelectionInitialMenu(int option)

Таким образом, он не соответствует сигнатуре указателя:

void (*switchStatement)()

что означает, что они несовместимы.

Ответ №2

Прежде всего, как только вы положите скобки после имени функции, вы больше не говорите о самой функции. i.e для бесплатных функций (функций, которые не являются членами класса) func относится к адресу функции func, тогда как func() относится к тому, что возвращается из этой функции.

У вас есть еще одна проблема. Вы пытаетесь передать нестационарную функцию-член класса как свободную функцию. Это не является законным в С++, поскольку нестатические функции-члены имеют скрытый аргумент, а именно объект, на который он ссылается. Хотя теоретически object.memberfunc может ссылаться на делегат, который при вызове вызывает memberfunc on object, он не находится в С++. Как обычно в С++, существует примерно один миллиард способов получить этот эффект с миллиардом компромиссов по различным критериям.

Я думаю, для вас проще всего использовать boost.bind. Итак, что вы пытаетесь сделать, будет выглядеть так:

#include<boost/bind.hpp>
using namespace boost;

...

template <class Functional>
void menuLoop(int numberOfOptions, Funcional displayMenu, void (*switchStatement)()){

...

menuLoop(3, bind(Menu::displayInitialMenu,menu), &performSelectionInitialMenu(3));

...

Ответ №3

menuLoop (3, & menu.displayInitialMenu(), & performSelectionInitialMenu (3));

Это не то, чего вы пытаетесь достичь. Во-первых, вы не можете принять адрес вещей, которые не являются переменными. Итак, вам нужно будет сделать следующее:

  • удалите “&”.
  • удалите “()” после displayInitialMenu и выполнитеSelectionInitialMenu, так как это означает, что эти функции будут вызываться, а возвращаемое значение, которое является недействительным в текущем случае, будет передано в menuLoop. Таким образом, вы не получите то, что вы пытаетесь достичь.

вам нужно сделать что-то вроде:

menuLoop (3, menu.displayInitialMenu, выполнитьSelectionInitialMenu, 3); Обратите внимание, что вам придется передать три в качестве дополнительного параметра.

а также соответственно изменить подпись menuLoop.

Fregat228

0 / 0 / 0

Регистрация: 24.11.2016

Сообщений: 11

1

11.12.2017, 23:47. Показов 2368. Ответов 1

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <conio.h>
using namespace std;
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL,"Russian");
    float xp,xk,dX,F,a,x,b,c,xc;
    cout<<"Введiть Xпоч, Xкін, dX, a, b, c:";
    cin>>xp>>xk>>dX>>a>>b>>c;
    for (x=xp;xc=xk;x+=dX)
        {
        if ((x<0.6)&&(b+c!=0))
        F=a*(x*x)+(b*b)+c;
            else
            if ((x>0.6)&&(b+c==0))
            F=(x-a)/(x-c);
                else
                F=(x/c)+(x/a);
        
        if ((int)a^(int)b)&~((int)c|0) ---------------в этом рядке проблема
        F=(int)F;
        cout<<x<<"\t"<<F<<endl;
        }
    getch();
    return 0;
}



0



Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Ошибка компилятора c2088
  • Ошибка кия р0626
  • Ошибка класс не зарегистрирован арм фсс
  • Ошибка кондиционера e16
  • Ошибка климатроника 25b

  • Добавить комментарий

    ;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: