函数重定义:const参数
function redefinition: const parameter
1。在全局范围内,这给出 error: redefinition of 'f'
#include <iostream>
using namespace std;
void f(int x) { cout << "f" << endl; }
void f(const int x) { cout << "f (const)" << endl; } // error: redefinition of 'f'
int main() { }
2。定义两个复制构造函数(一个带 const
,另一个不带)编译
#include <iostream>
using namespace std;
class Foo {
public:
Foo(const Foo&) { cout << "copy (const)" << endl; }
Foo(Foo&) { cout << "copy" << endl; }
};
int main() { }
问题
- 为什么 #1 是重定义错误而 #2 不是?
- 对于第二个例子,是否有定义两个复制构造函数的用例(一个有
const
另一个没有)?
- #1 是重定义错误,因为即使您修改了本地 x,它也是按值传递的,因此在 return 调用之后,值将保持不变。
两者有根本的区别。
一个是 int
和 const int
之间的过载。它是一种值类型。调用者没有语义差异,const
的效果只影响函数体。
void f(int);
int a = 1;
const int b = 2;
f(a); // must copy the int value into the argument
f(b); // same thing.
另一个是 const 与可变 reference。对于来电者来说是不同的。
void f(int&);
void f(const int&);
int a = 1;
const int b = 2;
f(a); // could call f(int&) or f(int const&), but the mutable is a more closely match
f(b); // can only call f(int const&);
由于它是通过引用传递的,所以常量对于函数的调用者很重要。尝试通过引用改变 const 对象的函数必须是无效的,并且默认情况下应将非 const 对象传递给非 const 重载。
只有价值观,根本无所谓。它是一个新对象。无论限定符如何,它对调用者都没有意义,因此不应该关心,因为它只影响实现。
您甚至可以在需要时在定义中添加 const,因为它声明了相同的函数:
void f(int);
int main() {
f(1);
}
void f(const int a) {
std::cout << "hello " << a << std::endl;
}
关于你的第二个问题,我想说的是,由于添加了右值引用,几乎不需要复制构造函数来获取可变引用。
例如,std::auto_ptr
曾经有一个构造函数采用可变引用来转移所有权,但它产生了各种问题。但它已经被std::unique_ptr
完全取代,它使用右值引用来转移所有权。
右值引用确保您不关心 copied-from 对象的完整性,并且可以从中窃取资源。
在检查两个函数是否相同时,只忽略top-levelconst
参数
“top-level”常量是什么意思?这意味着某些东西实际上是 const,如 std::is_const_v
.
所报告的那样
例如int *const
是top-levelconst(因为指针本身是const
),而const int *
不是(因为指针本身不是const
, 即使它指向 const
).
某些东西可以在多个级别上是常量,例如const int *const
.
const int
在顶层也是const,因为这里只有一个“层”。
如果您有不止一颗星(例如 int ***
),那么仅当 const
放在最右边的星之后时,类型才是 top-level const。
因此,const int
在顶层是 const,这意味着 const int
和 int
仅在 top-level constness 上有所不同。
但是(类似于 const int *
)const Foo&
不是 top-level 的常量。这是对 const Foo
的 non-const 引用。 (引用永远不能是 const1,例如 Foo &const
无法编译。)
所以Foo &
和const Foo &
之间的区别不在顶层,使得Foo(Foo &)
和Foo(const Foo &)
不同的构造函数。
1 有些人认为所有引用都是有效的 const
因为你不能让它们在创建后指向不同的对象。但是语言说他们不是 const
,std::is_const_v
returns 对他们来说是错误的。
1。在全局范围内,这给出 error: redefinition of 'f'
#include <iostream>
using namespace std;
void f(int x) { cout << "f" << endl; }
void f(const int x) { cout << "f (const)" << endl; } // error: redefinition of 'f'
int main() { }
2。定义两个复制构造函数(一个带 const
,另一个不带)编译
#include <iostream>
using namespace std;
class Foo {
public:
Foo(const Foo&) { cout << "copy (const)" << endl; }
Foo(Foo&) { cout << "copy" << endl; }
};
int main() { }
问题
- 为什么 #1 是重定义错误而 #2 不是?
- 对于第二个例子,是否有定义两个复制构造函数的用例(一个有
const
另一个没有)?
- #1 是重定义错误,因为即使您修改了本地 x,它也是按值传递的,因此在 return 调用之后,值将保持不变。
两者有根本的区别。
一个是 int
和 const int
之间的过载。它是一种值类型。调用者没有语义差异,const
的效果只影响函数体。
void f(int);
int a = 1;
const int b = 2;
f(a); // must copy the int value into the argument
f(b); // same thing.
另一个是 const 与可变 reference。对于来电者来说是不同的。
void f(int&);
void f(const int&);
int a = 1;
const int b = 2;
f(a); // could call f(int&) or f(int const&), but the mutable is a more closely match
f(b); // can only call f(int const&);
由于它是通过引用传递的,所以常量对于函数的调用者很重要。尝试通过引用改变 const 对象的函数必须是无效的,并且默认情况下应将非 const 对象传递给非 const 重载。
只有价值观,根本无所谓。它是一个新对象。无论限定符如何,它对调用者都没有意义,因此不应该关心,因为它只影响实现。
您甚至可以在需要时在定义中添加 const,因为它声明了相同的函数:
void f(int);
int main() {
f(1);
}
void f(const int a) {
std::cout << "hello " << a << std::endl;
}
关于你的第二个问题,我想说的是,由于添加了右值引用,几乎不需要复制构造函数来获取可变引用。
例如,std::auto_ptr
曾经有一个构造函数采用可变引用来转移所有权,但它产生了各种问题。但它已经被std::unique_ptr
完全取代,它使用右值引用来转移所有权。
右值引用确保您不关心 copied-from 对象的完整性,并且可以从中窃取资源。
在检查两个函数是否相同时,只忽略top-levelconst
参数
“top-level”常量是什么意思?这意味着某些东西实际上是 const,如 std::is_const_v
.
例如int *const
是top-levelconst(因为指针本身是const
),而const int *
不是(因为指针本身不是const
, 即使它指向 const
).
某些东西可以在多个级别上是常量,例如const int *const
.
const int
在顶层也是const,因为这里只有一个“层”。
如果您有不止一颗星(例如 int ***
),那么仅当 const
放在最右边的星之后时,类型才是 top-level const。
因此,const int
在顶层是 const,这意味着 const int
和 int
仅在 top-level constness 上有所不同。
但是(类似于 const int *
)const Foo&
不是 top-level 的常量。这是对 const Foo
的 non-const 引用。 (引用永远不能是 const1,例如 Foo &const
无法编译。)
所以Foo &
和const Foo &
之间的区别不在顶层,使得Foo(Foo &)
和Foo(const Foo &)
不同的构造函数。
1 有些人认为所有引用都是有效的 const
因为你不能让它们在创建后指向不同的对象。但是语言说他们不是 const
,std::is_const_v
returns 对他们来说是错误的。