2

这是一个(希望如此)非常简单的问题——最近有人告诉我,使用 C++ 风格的初始化比传统的(更常见的)赋值要好。

所以这段代码:

std::SomeSTLContainer::const_iterator it = container.begin();
std::SomeSTLContainer::const_iterator itEnd = container.end();

将比以下“慢”或效率低:

std::SomeSTLContainer::const_iterator it ( container.begin() );
std::SomeSTLContainer::const_iterator itEnd ( container.end() );

我理解这样做的原因 - 第一个示例导致默认构造和初始化,然后是后续分配,而不是第二个示例中的特定构造和直接分配。但是,在现代处理器/编译器上,它真的有什么不同吗?

4

5 回答 5

9

最近有人告诉我,使用 C++ 风格的初始化比传统的(和更常见的)赋值要好。

这是完全错误的。

我理解这样做的原因 - 第一个示例导致默认构造和初始化,然后是后续分配,而不是第二个示例中的特定构造和直接分配。但是,在现代处理器/编译器上,它真的有什么不同吗?

不,这没有什么区别。C++ 标准明确允许在这种情况下省略赋值,以便生成相同的代码。实际上,所有现代 C++ 编译器都这样做。

此外,Charles 是对的:这永远不会调用赋值运算符,而是调用复制构造函数。但正如我所说,即使这样也不会发生。

于 2009-02-09T10:29:06.163 回答
3

你的推理不太正确。在定义中使用“=”不会导致默认构造和赋值。在“最坏”的情况下,它使用从“=”右侧生成的临时的复制构造函数。

如果右侧的类型是(除了常量/易失性)相同类型或被初始化对象的派生类型,那么这两种构造形式是等价的。

于 2009-02-09T10:29:44.240 回答
0

不,通常。这是因为迭代器被编码为非常薄的包装器,而优化器在涉及到薄包装器时非常激进。例如,普通的迭代器方法只是一个简单的指针操作,函数体可以从头文件中获得。这使得它可以简单地内联。在这种情况下,迭代器副本在幕后可能只是一个指针副本,所以同样成立。

于 2009-02-09T10:31:02.350 回答
0

这实际上取决于具体情况,应该应用一般的经验法则:measure

如果这些迭代器有很多实例化(可能在嵌套和排序循环中,那些较短的构造函数很容易产生影响)。尽管正如您所建议的那样,许多编译器已经可以自己优化它们。

要真正确定您的编译器是否这样做,只有一种方法:测量

于 2009-02-09T10:31:23.567 回答
0
A a = A( arg1, arg2, ... );

正如鲁道夫所说,这个赋值可以用一个简单的结构代替:它是一个结构。事实上,它会被编译成更简洁的等价物

A a( arg1, arg2, ...);

这主要是一个样式问题,但我不喜欢将“分配样式”结构与“初始化器样式”结构混合在一起。通过这种方式,我可以在整个代码中引入一致性。这归结为:始终使用初始化程序样式构造:)。

于 2009-02-09T12:08:18.543 回答