c++ - 我还应该在 C++11 中返回 const 对象吗?

标签 c++ performance c++11 constants

Possible Duplicate:
Should I return const objects?
(The original title of that question was: int foo() or const int foo()? explaining why I missed it.)


Effective C++,第 3 条:尽可能使用 const。特别是,返回 const 对象被提升以避免像 if (a*b = c) { 这样的意外赋值。我觉得这有点偏执,但我一直遵循这个建议。

在我看来,返回 const 对象会降低 C++11 的性能。

#include <iostream>
using namespace std;

class C {
public:
    C() : v(nullptr) { }

    C& operator=(const C& other) {
        cout << "copy" << endl;
        // copy contents of v[]
        return *this;
    }

    C& operator=(C&& other) {
        cout << "move" << endl;
        v = other.v, other.v = nullptr;
        return *this;
    }

private:
    int* v;
};

const C const_is_returned() { return C(); }

C nonconst_is_returned() { return C(); }

int main(int argc, char* argv[]) {
    C c;
    c = const_is_returned();
    c = nonconst_is_returned();
    return 0;
}

打印出来:

copy
move

我是否正确实现了移动分配?或者我根本不应该在 C++11 中返回 const 对象?

最佳答案

返回 const 对象是一种可能导致其他问题的解决方法。从 C++11 开始,赋值问题有了更好的解决方案:Reference Qualifiers 用于成员函数。我尝试用一​​些代码来解释它:

int foo(); // function declaration
foo() = 42; // ERROR

第二行中的赋值导致 C 和 C++ 中内置类型 int 的编译时错误。其他内置类型也一样。这是因为内置类型的赋值运算符需要左侧的非常量左值引用。把它放在代码中,赋值运算符可能如下所示(无效代码):

int& operator=(int& lhs, const int& rhs);

在 C++ 中总是可以将参数限制为左值引用。但是,在 C++11 之前,对于成员函数的隐式第一个参数 (*this),这是不可能的。

C++11 改变了这一点:类似于成员函数的 const 限定符,现在有成员函数的引用限定符。以下代码展示了复制和移动操作符的用法(注意参数列表后面的&):

struct Int
{
    Int(const Int& rhs) = default;
    Int(Int&& rhs) noexcept = default;
    ~Int() noexcept = default;
    auto operator=(const Int& rhs) & -> Int& = default;
    auto operator=(Int&& rhs) & noexcept -> Int& = default;
};

使用此类声明,以下代码片段中的赋值表达式无效,而分配给局部变量有效 - 就像在第一个示例中一样。

Int bar();
Int baz();
bar() = baz(); // ERROR: no viable overloaded '='

所以没有必要返回 const 对象。您可以将赋值运算符限制为左值引用,以便其他一切仍按预期工作 - 特别是移动操作。

另见:

关于c++ - 我还应该在 C++11 中返回 const 对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13099942/

相关文章:

c++ - 紧接着声明的变量地址是否在彼此之前?

c++ - 将 std::cout 添加到全局运算符新掩码 SIGSEGV

c++ - 删除指针 vector

r - 如何避免函数which()中具有多个条件的for循环

c++ - 在Boost program_options中的配置文件中处理无值选项

c# - 在 .NET 上更快地解析数字

c++ - 为什么 std::atomic<bool> 比 volatile bool 慢得多?

c++ - 基于 CRTP 的解决方案会是什么样子?

c++ - 如何使用 'auto' 关键字迭代 C++ STL 映射数据结构?

c++ - 类型比较