为什么 const 按值结构绑定允许用户修改引用的变量?
Why const by-value structural binding allows the user to modify referenced variable?
我对结构绑定很困惑。即使我使用 const
和按值(没有 &
)结构绑定,如本例所示:
#include <iostream>
#include <tuple>
int main()
{
int x = 0;
std::tuple<int&> p(x);
const auto [a] = p;
a++;
std::cout << x << '\n';
}
它仍然修改x
并打印1
:https://gcc.godbolt.org/z/jc8hxE8M6
如果我在 [a]
之前添加 &
或删除 const
,您能否解释一下为什么它会这样工作并希望更改?
参见 cppreference 上的示例:
The portion of the declaration preceding [
applies to the hidden
variable e, not to the introduced identifiers.
int a = 1, b = 2;
const auto& [x, y] = std::tie(a, b); // x and y are of type int&
auto [z, w] = std::tie(a, b); // z and w are still of type int&
assert(&z == &a); // passes
其中e
指的是
A structured binding declaration first introduces a uniquely-named variable (here denoted by e) to hold the value of the initializer, as follows: [...]
您示例中的 const
不适用于 a
,下一个示例说明了为什么它仍然有用:
int a = 1;
const auto& [x] = std::make_tuple(a); // OK, not dangling
auto& [y] = std::make_tuple(a); // error, cannot bind auto& to rvalue std::tuple
auto&& [z] = std::make_tuple(a); // also OK
编译器推导出类似下面的类型
typedef int & Ref;
这是std::tuple
对象的元素类型。
如果你会再写例如
int x = 0;
const Ref rx = x;
那么最后一个声明等同于
int & const rx = x;
但与指针相反,在这个意义上,引用可能不是常量。所以限定符 const 被忽略了,你有
int & rx = x;
这是一个演示程序。
#include <tuple>
#include <type_traits>
int main()
{
int x = 0;
std::tuple<int &> p( x );
const auto [a] = p;
std::cout << std::is_same_v<decltype( a ), int &> << '\n';
std::tuple<int *> p1( &x );
const auto [b] = p1;
std::cout << std::is_same_v<decltype( b ), int * const> << '\n';
}
程序输出为
1
1
我对结构绑定很困惑。即使我使用 const
和按值(没有 &
)结构绑定,如本例所示:
#include <iostream>
#include <tuple>
int main()
{
int x = 0;
std::tuple<int&> p(x);
const auto [a] = p;
a++;
std::cout << x << '\n';
}
它仍然修改x
并打印1
:https://gcc.godbolt.org/z/jc8hxE8M6
如果我在 [a]
之前添加 &
或删除 const
,您能否解释一下为什么它会这样工作并希望更改?
参见 cppreference 上的示例:
The portion of the declaration preceding
[
applies to the hidden variable e, not to the introduced identifiers.int a = 1, b = 2; const auto& [x, y] = std::tie(a, b); // x and y are of type int& auto [z, w] = std::tie(a, b); // z and w are still of type int& assert(&z == &a); // passes
其中e
指的是
A structured binding declaration first introduces a uniquely-named variable (here denoted by e) to hold the value of the initializer, as follows: [...]
您示例中的 const
不适用于 a
,下一个示例说明了为什么它仍然有用:
int a = 1; const auto& [x] = std::make_tuple(a); // OK, not dangling auto& [y] = std::make_tuple(a); // error, cannot bind auto& to rvalue std::tuple auto&& [z] = std::make_tuple(a); // also OK
编译器推导出类似下面的类型
typedef int & Ref;
这是std::tuple
对象的元素类型。
如果你会再写例如
int x = 0;
const Ref rx = x;
那么最后一个声明等同于
int & const rx = x;
但与指针相反,在这个意义上,引用可能不是常量。所以限定符 const 被忽略了,你有
int & rx = x;
这是一个演示程序。
#include <tuple>
#include <type_traits>
int main()
{
int x = 0;
std::tuple<int &> p( x );
const auto [a] = p;
std::cout << std::is_same_v<decltype( a ), int &> << '\n';
std::tuple<int *> p1( &x );
const auto [b] = p1;
std::cout << std::is_same_v<decltype( b ), int * const> << '\n';
}
程序输出为
1
1