提问人:Eduard Nicodei 提问时间:7/28/2019 更新时间:7/28/2019 访问量:142
为什么即使参数标记为“const”,也会调用复制构造函数?
Why is copy constructor called even when parameter is marked 'const'?
问:
请考虑以下两个函数:
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);
编译器似乎仍然将一个临时对象(通过复制构造函数创建)传递给 ( https://godbolt.org/z/p2ID1dfoo
)
它为什么要这样做?x 是 const,因此它不会被 改变,因此编译器仍然应该能够以与调用相同的方式直接传递。foo
a
foo2(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&)
我猜答案与 的定义中被删除的事实有关,但我不知道为什么。对不起,如果我错过了一些明显的东西。const
foo
谢谢!
答:
0赞
Sid S
7/28/2019
#1
按值传递时,编译器必须创建一个副本。
按值传递的效果只是不允许函数修改它接收的副本。这样做比路过没有好处 - 相反,它的效率较低,因为它涉及副本。const
const &
1赞
Thomas Sablik
7/28/2019
#2
编译器不优化它是对的。你可以做这样的事情
#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;
}
这甚至可能发生在后台,编译器不会知道。
3赞
Nikos C.
7/28/2019
#3
对于非引用参数,当编译器存储函数的签名时,实际上会忽略它。例如,给定以下函数原型:const
void func(std::string);
func
可以使用此签名实现:
void func(const std::string) // This is NOT an overload.
{}
因此,对如何传递值参数没有任何影响。它们被复制。仅对参数在函数实现中的使用方式有影响。const
const
评论