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

时间:2011-06-24 10:36:51

标签: c++

3.10 / 10,标准说:

  

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

因此,除非在某些情况下,否则rvalues是不可修改的。我们被告知调用成员函数是其中一个例外。这给出了除了调用成员函数之外还有修改对象的方法的想法。我想不出办法。

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

7 个答案:

答案 0 :(得分:3)

  

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

我只知道一种方法,即将对象绑定到const的引用,然后抛弃const -

E.g。

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的答案显示了另一种(非一般)方式,即临时的构造在某个可访问的位置存储一些引用或指向对象的指针。< / p>

干杯&amp;第h。,

答案 1 :(得分:2)

seems to be accepted

struct T {
   int x;
};

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

我有点惊讶这是有效的,因为IIRC op=的LHS必须是左值,但以下暗示even T().x is an rvalue

struct T {
   int x;
};

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

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

修改:自4.6起,GCC 警告T().x = 3error: using temporary as lvalue

除了通过数据成员访问或成员函数调用之外,我无法想到修改类对象的任何其他方法。所以,我要说...... 你不能

答案 2 :(得分:1)

修改临时而非通过左值的临时值:

#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) );
}

我不认为假设类类型的rvalues是不可修改的是正确的。我现在理解该段落为'对于非类类型,为了修改该对象需要对象的左值'。

答案 3 :(得分:0)

我可以想到一种方式:

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

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

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

这不是一个好的编程风格 - 将成员变量公开为公开并不是我所倡导甚至建议的。

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

答案 4 :(得分:0)

  

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

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

答案 5 :(得分:0)

执行隐式转换有点像调用成员函数 - 修改rvalue refs似乎也有效。

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

答案 6 :(得分:-1)

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

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

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