Подтвердить что ты не робот

Как вы можете изменить объект без вызова функций-членов?

В 3.10/10 в стандарте говорится:

Для изменения объекта требуется lvalue для объекта, за исключением того, что rvalue типа класса также может использоваться для изменения его референта при определенных обстоятельствах. [Пример: функция-член, вызываемая для объекта (9.3), может изменять объект. ]

Таким образом, значения r не изменяются, за исключением определенных условий. Нам говорят, что вызов функции-члена является одним из тех исключений. Это дает представление о том, что существуют способы изменения объектов, кроме вызова функции-члена. Я не могу придумать способ.

Как можно изменить объект без вызова функции-члена?

4b9b3361

Ответ 1

Как можно изменить объект [, указанный выражением rvalue] без вызова функции-члена?

Я знаю только один способ сделать это: привязать объект к ссылке на const, а затем отбросить const -ness.

например.

template< class Type >
Type& tempRef( Type const& o ) { return const_cast< Type& >( o ); }

struct S { int x; };

int main()
{ tempRef( S() ).x = 3; }

Это связано с тем, что временный объект не является const, если он не имеет тип const, поэтому приведенный выше пример не отбрасывает оригинальную const -ness (которая будет UB).

EDIT, добавлено: Luc Danton & rsquo; s ответ показал другой (не общий) способ, а именно, где временная конструкция хранит некоторые ссылку или указатель на объект в некотором доступном месте.

Приветствия и hth.,

Ответ 2

Этот считается принятым:

struct T {
   int x;
};

int main() {
   T().x = 3;
}

Я немного удивлен, что это работает, потому что IIRC LHS op= должен быть lvalue, но из следующего следует, что even T().x является Rvalue:

struct T {
   int x;
};

void f(int& x) {
   x = 3;
}

int main() {
   f(T().x);
}

Изменить: Начиная с версии 4.6, GCC предупреждает о T().x = 3: error: using temporary as lvalue.

Я не могу придумать другого способа изменить объект класса, кроме как через доступ к члену данных или вызовы функций-членов. Итак, я собираюсь сказать... вы не можете.

Ответ 3

Изменение временного, а не через lvalue для этого временного:

#include <cstring>

class standard_layout {
    standard_layout();
    int stuff;
};

standard_layout* global;

standard_layout::standard_layout()
{ global = this; }

void
modify(int)
{
    std::memset(global, 0, sizeof *global);
}

int
main()
{
    modify( (standard_layout {}, 0) );
}

Я не думаю, что правильно предположить, что значения типов классов не изменяются. Теперь я понимаю, что абзац как "для типов некласса, для изменения этого объекта требуется lvalue для объекта".

Ответ 4

Я могу думать об одном способе:

Если ваш класс предоставляет публичные переменные-члены, вы можете напрямую назначить эти переменные-члены. Например:

class A
{
    public:
        int _my_var;
...
};

int main(int argc, char** argv)
{
    A *a = new C();
    a->_my_var = 10;
}

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

Кроме того, если вы можете сделать что-то действительно странное, например, непосредственно написать какой-то адрес в памяти, смещение от указателя на объект класса, но зачем вы это делаете?

Ответ 5

Как можно изменить объект без вызова функции-члена?

Назначение значения одному из видимых элементов данных объекта, конечно.

Ответ 6

Выполнение неявного приведения похоже на вызов функции-члена, также, похоже, работает обработка rvalue ref.

Протестировано следующее в vС++ 10 и g++ 4.4.

struct b { int i; b(int x) : i(x) {} };
struct a { int i; a() : i(0) { } operator b() { return i++ /* this works */, b(i); } };
a f(a&& x) { return x.i++ /* this works */, x; }
int main() { b b = f(a()); /* implicit operator b() cast; b.i will equal 2 */ }

Ответ 7

Функция-член может напрямую изменять элемент, но он также может делегировать эту ответственность:

struct Foo {
  int x;
  void Bar() { scanf("%d", &x); }
};

Текущая формулировка стандарта имеет то преимущество, что не нужно утверждать, является ли это случаем Bar изменения объекта. Если мы согласны с тем, что scanf изменяет объект, то это еще один пример.