-3

我知道使用对象的自分配不是一个好主意,显然没有人明确地进行过这样的自分配。

MyClass obj;
obj = obj;

C++有什么理由支持这个,或者有什么特殊情况可以使用它?

4

5 回答 5

2

除了 Carl Norum 和 Ralph Tandetzky 已经发布的答案之外,问问自己编译器是否可以检测到所有可能的自赋值。

答案应该很明显,不,它不能。考虑这个相当简单(和愚蠢)的代码片段:

   Class obj1;
   Class obj2;

   Class *ptr = &obj1;

   if((rand() % 7) == 0)
       ptr = &obj2;

   obj2 = *ptr;

此代码有时会导致自分配。编译器应该警告你吗?什么?“ Heisenberg 错误 #3:返回 7 的倍数时的自赋值rand()? ” 如果您rand只返回 [0, 6] 范围内的数字怎么办?

这是一个简单的例子,编译器可以很容易地弄清楚。有更多复杂的代码片段更难捕捉,但如果编译器对代码执行广泛的流分析,则可能会被捕捉到,但运行时间会更长。而且,当然,有非常复杂的代码片段可以表现出这种很难甚至不可能捕捉到的行为。

因此,您可能拥有一个运行时间更长的编译器,只是有时会概率性地警告您潜在的自分配。坦率地说,这比没有警告更糟糕。

如果您觉得这是一个问题并且您不想允许它,那么有一个编码标准,上面写着“没有自我分配!” 可能是更好的主意。


旁注:有一些工具可以进行很多非常复杂的源代码分析来尝试根除问题;此类工具可以配置为并将捕获许多此类自分配,包括一些复杂的自分配。但是他们仍然没有抓住一切,需要一段时间才能运行并且通常花费数千美元。

于 2013-07-23T18:00:52.130 回答
1

我想没有理由禁止它。你为什么要?创建额外的语言规则?据我所知,自我分配并没有真正的用途。

有充分的理由允许在分配的两边都有一个对象,例如

obj = f( obj );

线

obj = obj;

真的只是其中的一个特例。

于 2013-07-23T17:32:48.193 回答
0

我认为这是可能的。就像您可以在汇编中移动同一寄存器本身的值一样:

mov eax, eax

它恰好适合通用的设计。

于 2013-07-23T17:31:57.423 回答
0

这可能是允许的,因为没有真正的理由禁止它。我已经看到它被用作未使用变量警告的解决方法,尽管我个人不推荐这种用法。

于 2013-07-23T17:32:32.450 回答
0

对于 POD 对象或没有构造函数的对象,可以使用它来抑制“ may be used before initialized”警告(如果声明的局部变量确实未被使用,则应将其删除)。

在文件或命名空间范围内,它可以用作防止初始化其他全局对象的构造函数正在使用的全局对象的技巧。

std::list<Foo> g_foos;

Foo如果添加到g_foosbefore的静态实例g_foos::g_foos()开始运行,则列表将自己清空,并且注册将丢失。自初始化可以防止这种情况。

std::list<Foo> g_foos = g_foos;

但是有更好的方法来实现一个全局实例,也可以防止这个问题,例如:

std::list<Foo> & the_foos () {
    static std::list<Foo> foos;
    return foos;
}
于 2013-07-23T18:58:11.747 回答