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

В 3.10/10 стандарт гласит:

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

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

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

7 ответов

Как можно изменить объект [который указан выражением 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-несс (что было бы UB).

РЕДАКТИРОВАТЬ, добавил: Ответ Люка Дантона показал другой (не общий) способ, а именно, где конструкция временного хранит некоторую ссылку или указатель на объект в некотором доступном месте.

Ура & hth.,

Кажется, это принято:

struct T {
   int x;
};

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

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

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,

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

Изменение временного а не через 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 для объекта".

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

Проверено следующее в vC++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 */ }

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам