如何在不调用成员函数的情况下修改对象

How can you modify an object without calling member functions?

本文关键字:情况下 修改 对象 函数 成员 调用      更新时间:2023-10-16

在3.10/10时,标准规定:

为了修改对象,对象的左值是必要的,除了类类型的右值在某些情况下也可以用来修改其引用。[示例:为对象(9.3)调用的成员函数可以修改该对象。]

因此,除非在某些情况下,右值是不可修改的。我们被告知,调用成员函数就是其中一个例外。这就产生了这样一种想法,即除了调用成员函数之外,还有其他方法可以修改对象。我想不出办法了。

如何在不调用成员函数的情况下修改对象?

如何在不调用成员函数的情况下修改对象[由右值表达式指定]?

我知道只有一种方法可以做到这一点,即将对象绑定到对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)。

编辑,添加:Luc Danton’s的回答显示了另一种(非通用)方式,即临时结构在某个可访问的位置存储对象的一些引用或指针。

干杯&hth。,

这似乎是可以接受的:

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

我对这一点有点惊讶,因为IIRC——op=的LHS——必须是一个左值,但以下暗示即使是T().x也是一个右值:

struct T {
   int x;
};
void f(int& x) {
   x = 3;
}
int main() {
   f(T().x);
}

编辑:自4.6起,GCCT().x = 3:error: using temporary as 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) );
}

我认为假设类类型的右值是不可修改的是不对的。我现在将该段落理解为"对于非类类型,需要对象的左值才能修改该对象"。

我可以想出一种方法:

如果您的类公开公共成员变量,则可以直接分配给这些成员变量。例如:

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

不过,这不是一种好的编程风格——将成员变量公开为公共变量并不是我所提倡甚至建议的。

此外,如果你可以做一些非常奇怪的事情,比如直接在内存中写一些地址,从指针到类对象的偏移量——但你为什么要这样做呢?

如何在不调用成员函数的情况下修改对象?

当然,通过为对象的一个可见数据成员指定值。

执行隐式强制转换有点像调用成员函数——同时修改右值引用似乎也有效。

在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 */ }

成员函数可以直接更改成员,但也可以委派该职责:

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

该标准的当前措辞的优点是,不需要争论这是否是Bar更改对象的情况。如果我们同意scanf更改对象,那么这只是另一个例子。

相关文章: