【问题标题】:Can modern C++ compilers optimise the assignment operator for temporary variables?现代 C++ 编译器可以优化临时变量的赋值运算符吗?
【发布时间】:2020-11-19 10:49:48
【问题描述】:

下面是MyStruct 类实现,它具有默认构造函数和复制构造函数。

struct MyStruct {
    MyStruct(const string& name) {
        cout << "Basic constructor called" << endl;
        name_ = name;
    }
    MyStruct(const MyStruct& S) {
        cout << "Copy constructor called" << endl;
        name_ = S.name_;
    }
    string name_;
}

以下列方式创建对象:MyStruct S = MyStruct("Hello"); 使用“Hello”参数调用构造函数。我怀疑我的编译器(gcc 版本 7.5.0)通过避免创建临时对象来进行优化MyStruct("Hello") 对象。

但是,编译器并没有优化赋值运算符的类似情况:

MyStruct& operator=(const string& name) { // First assignment operator
    name_ = name;
    return *this;
}
MyStruct& operator=(const MyStruct& S) { // Second assignment operator
    name_ = S.name_;
    return *this;
}

将 S 重新分配给另一个结构:

MyStruct S = MyStruct("Hello"); // initial construction
S = MyStruct("world"); // reassignment

第二次调用构造函数来构造临时的MyStruct("world") 对象。之后,调用第二个赋值运算符。

问题

  • 有没有办法修改代码,以便调用带有参数"world" 的第一个赋值运算符?

  • 是现代 C++ 标准的第一个优化部分(即适用于所有编译器),还是仅适用于特定编译器?

【问题讨论】:

  • 如果要调用MyStruct&amp; operator=(const string&amp; name),则需要像S = "world";一样将字符串直接赋值给S
  • 编译器不能通过赋值来做到这一点。采用参数和赋值运算符的构造函数是用户定义的函数。而那些可以做......任何事情。编译器无法证明调用operator=(const string&amp;) 与调用MyStruct(const string&amp;) 然后调用operator=(const MyStruct&amp;) 具有相同的行为。它不能进行改变行为的优化。
  • "现代 C++ 编译器能否优化临时变量的赋值运算符?" - 为什么不简单地使用启用优化的现代编译器编译代码并检查生成的程序集?这将明确回答您的问题。
  • @mercury - 这在 C++ 的早期是不可能的。但是...对于构造函数,您没有 existing 对象被修改(可能具有不变量)。它只是需要初始化的存储。在这种情况下,可观察行为的变化被认为更合理,因此被标准允许。

标签: c++ c++11 constructor copy-constructor forwarding


【解决方案1】:

有没有办法修改代码,以便调用带有参数“world”的第一个赋值运算符?

当然:

S = "world";

我怀疑我的编译器(gcc 版本 7.5.0)通过避免创建临时文件来进行优化

是现代 C++ 标准的第一个优化部分

自 C++17 以来没有临时的,因此保证不会调用复制构造函数。

在 C++17 之前,有一个临时对象,编译器只允许不调用复制构造函数(从而优化临时对象)。所有主要编译器都实现了这种优化。

【讨论】:

    猜你喜欢
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多