为什么即使参数标记为"const",也会调用复制构造函数?

Why is copy constructor called even when parameter is marked 'const'?

本文关键字:调用 复制 构造函数 const 参数 记为 为什么      更新时间:2023-10-16

考虑以下两个函数:

int foo(const std::string x) {
    return x.length();
}
int foo2(const std::string& x2) {
    return x2.length();
}

呼叫时

std::string a("hello world!");
foo(a);

编译器似乎仍然将临时对象(通过复制构造函数创建(传递给foo(https://godbolt.org/z/p2ID1d (

x是常量,因此它不会被foo改变,因此编译器仍然应该能够以与调用foo2(a)相同的方式直接传递a

旁注:我正在查看 godbolt 生成的函数类型:

foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
foo2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

我猜答案与constfoo的定义中删除的事实有关,但我不知道为什么。 对不起,如果我错过了一些明显的东西。

谢谢!

对于非引用参数,当编译器存储函数的签名时,实际上会忽略const。例如,给定此函数原型:

void func(std::string);

可以使用以下签名实现func

void func(const std::string) // This is NOT an overload.
{}

因此const对值参数的传递方式没有任何影响。它们被复制。const仅影响参数在函数实现中的使用方式。

编译器不优化它是对的。你可以做类似的事情

#include <iostream>
#include <thread>

void foo(const std::string x) {
    using namespace std::chrono_literals;
        std::this_thread::sleep_for(1s);
    std::cout << x.length() << 'n';
}
int foo2(const std::string& x2) {
    using namespace std::chrono_literals;
        std::this_thread::sleep_for(1s);
    std::cout << x2.length() << 'n';
}
int main() {
    std::string a("hello world!");
    std::thread t1([&]{
        foo(a);
    });
    std::thread t2([&]{
        foo2(a);
    });
    a = "";
    t1.join();
    t2.join();
    return 0;
}

这甚至可能发生在后台,编译器不会知道。

按值传递时,编译器必须创建一个副本。

传递const值的效果只是不允许函数修改它接收的副本。 这样做比通过const &没有任何好处 - 相反,它的效率较低,因为它涉及副本。