为什么即使参数标记为"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);
编译器似乎仍然将临时对象(通过复制构造函数创建(传递给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&)
我猜答案与const
在foo
的定义中删除的事实有关,但我不知道为什么。 对不起,如果我错过了一些明显的东西。
谢谢!
对于非引用参数,当编译器存储函数的签名时,实际上会忽略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 &
没有任何好处 - 相反,它的效率较低,因为它涉及副本。
相关文章:
- 当从函数参数中的临时值调用复制构造函数时
- 为什么调用复制构造函数而不是移动构造函数?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 编译器调用复制运算符而不是移动运算符
- push_back std::vector,则重复调用复制构造函数
- 为什么调用复制构造函数来构造空unique_ptr向量?
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 我打算调用initializer_list构造函数,如果存在,则事先调用复制构造函数:为什么?
- C++ - 从移动分配运算符调用复制分配
- 构造函数初始值设定项列表未调用复制构造函数
- 为什么在我的代码中调用复制构造函数而不是移动构造函数?
- std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数
- 通过引用传递对象时是否调用复制构造函数?
- 如果函数按值传递并按值返回,将调用复制构造函数多少次
- 为什么要抛出引用调用复制构造函数的异常?
- 为什么即使参数标记为"const",也会调用复制构造函数?
- Clang-Tidy:移动构造函数通过调用复制构造函数来初始化类成员
- 为什么当我添加一个不同的对象(复制构造函数中的参数)时调用复制构造函数?
- 为什么调用复制构造函数,当我只返回对象 c++ 的引用时
- 为什么在下面的代码中调用复制构造函数两次