当我初始化 C++容器(例如 std::list)是否调用了复制构造函数?

发布于 2024-12-07 07:06:14 字数 235 浏览 0 评论 0原文

当我初始化一个 STL 容器(例如 listlist<矢量> 使用例如 my_list.push_back(vector(5000, 'T')) 这是在构造后复制的吗?或者编译器是否调用 list内的构造函数?矢量> 本身?

When I initialize a STL container such as a list< vector<char> > using e.g. my_list.push_back(vector<char>(5000, 'T')) is this copied after construction? Or does the compiler invoke the constructor inside list< vector<char> > itself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最冷一天 2024-12-14 07:06:14

在 C++03 中,push_back 定义为 void Push_back(const T& x);。这意味着您正在构造一个向量,并且对此类时间的 const 引用将传递到列表。然后,list 在内部调用复制构造函数来存储此类元素的副本。

在 C++11 中,有一个额外的 void Push_back(T&& x); 定义,它采用对时间 向量 的右值引用,并会导致内部调用移动构造函数来初始化 list 所保存的副本。

In C++03 push_back is defined as void push_back(const T& x);. That means that you are constructing a vector and a const reference to such temporal is being passed to the list. Then the list internally invokes the copy constructor in order to store a copy of such element.

In C++11 there is an extra definition for void push_back(T&& x); that takes an rvalue reference to your temporal vector, and would result in the move constructor being called internally to initialize the copy held by the list.

江南烟雨〆相思醉 2024-12-14 07:06:14

编译器很聪明。真的很聪明。在这种情况下,有一种称为“复制省略”的优化。 C++ 标准允许编译器在使用临时对象来初始化相同类型的对象时省略副本,并且该对象的复制构造函数没有副作用。

这与更流行的“好像”规则属于同一类优化。该规则允许编译器几乎可以摆脱它想要的任何东西,只要生成的程序的可观察行为与“就好像”完全遵循了标准一样。

这是一个示例程序。在 gcc 4.4.5 上,同时使用 -O0 和 -O3 时,此代码会打印“1”。我认为 GCC 在这里是错误的......一些编译器会输出“2”,表明发生了复制。这就是试图检测本应无法检测到的行为时变得棘手的地方。在其中一个编译器中,唯一的判断方法是深入研究生成的程序集。

#include <iostream>

struct elision
{
    explicit elision(int i) : v(i) {
    }

    elision(elision const ©) : v(copy.v+1) {
    }

    int v;
};

int main()
{
    elision e(elision(1));
    std::cout << e.v << std::endl;
    return 0;
}

Compilers are smart. Really smart. In this case, there is an optimization called "copy elision." The C++ standard allows the compiler to omit a copy when a temporary object is used to initialize an object of the same type and the copy constructor of said object has no side effects.

This is in the same class of optimizations as the more popular "as if" rule. That rule allows the compiler to get away with nearly anything it wants, as long as the observable behavior of the resulting program is the same "as if" the standard had been followed exactly.

Here is an example program. On gcc 4.4.5 with both -O0 and -O3 this code results in a "1" being printed. I think that GCC is wrong here... some compilers will output "2" indicating a copy took place. This is where things get tricky in trying to detect behavior that is supposed to be undetectable. In one of those compilers, the only way to tell will be to dive into the resulting assembly.

#include <iostream>

struct elision
{
    explicit elision(int i) : v(i) {
    }

    elision(elision const ©) : v(copy.v+1) {
    }

    int v;
};

int main()
{
    elision e(elision(1));
    std::cout << e.v << std::endl;
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文