我遇到了一個我認為很奇怪的事情:
我遇到了一個我認為很奇怪的事情。
#include <vector>
int numqueues = 1;
std::vector<float> priorities{numqueues, 1.f };
//^^ warning: narrowing conversion of numqueues from int to float.
//std::vector<float> priorities(numqueues, 1.f );
//^^^ 沒有警告或錯誤。而且這并不是因為它被決議為一個函式宣告。
//^^因為我可以在main中呼叫push_back。
int main()
{
priorities.push_back(1);//不需要縮小轉換。
}
我已經用幾個編譯器試過了,這不會被編譯。
編輯:有人說initializer_list優先,看起來是這樣的,但是我試著模仿std::vector,在這個例子中我沒有得到縮小轉換的錯誤:
template <typename T>
class MyVector
{public:
MyVector(size_t s, float f) {
std::cout << "已呼叫建構式
"。
}
MyVector(std::initializer_list< T> init)
{
std::cout << "呼叫了初始化器串列建構式
"。
}
};
int main()
{
MyVector<float> foo{ size_t(3), 2.f };
}
我做了完全相同的事情,用size_t和float進行初始化,就像在另一個例子中一樣,這個例子的編譯很好。
uj5u.com熱心網友回復:
在這個宣告中
std::vector<float> priorities{numqueues, 1.f }。
編譯器使用初始化串列構造器。
vector(initializer_list<T>, const Allocator& = Allocator() )。)
禁止初始化器串列的縮小轉換。
在這個宣告中
std:: vector<float> priorities(numqueues, 1. f )。
編譯器使用了指定元素數量及其初始化器的構造器。
vector(size_type n, const T& value, const Allocator& = Allocator()) 。
來自C 14標準(8.5.4串列初始化)
2 一個建構式是一個初始化串列建構式,如果它的第一個 的第一個引數是std::initializer_list型別或對可能的 cv限定的std::initializer_list型別,并且要么沒有其他引數,要么所有引數都是 沒有其他引數,否則所有其他引數都有 默認引數(8.3.6)。[注意:初始化器串列建構式比串列中的其他建構式更受歡迎。 在串列初始化中比其他建構式更受青睞
。
和(13.3.1.7 通過list-initialization進行初始化)
1 當非集合型別別T的物件被串列初始化,以便 8.5.4規定了根據本節的規則進行多載決議。 的規則進行,多載決議會在兩個階段選擇 建構式,分為兩個階段:
(1.1)
(1.1) - 最初,候選函式是初始化器串列中的 建構式(8.5.4),引數串列包括
(1.2)
(1.2) - 如果沒有找到可行的初始化器串列建構式,則再次進行多載決議。 再度進行多載決議,其中候選函式是類 T 的所有建構式和 候選函式都是類T的建構式,而引數串列由初始化器串列的部分組成。
下面是一個示范性程式
結構 A
{
A( std::initializer_list< float> )
{
std::cout << "A( std::initializer_list< float> )
"。
}
A( size_t, float )
{
std::cout << "A( size_t, float )
"。
}
};
int main()
{
A a1 { 1, 1.0f };
A a2( 1, 1.0f ) 。
return 0。
程式輸出是
A( std::initializer_list< float> )
A( size_t, float )
至于你附加的問題,那么(8.5.4 串列初始化)
7 縮小的轉換是一種隱含的轉換
(7.3) - 從一個整數型別或無范圍的列舉型別到一個 浮點型別,除非源是一個常數運算式,并且轉換后的實際值將是一個常數運算式。 運算式,并且轉換后的實際值將適合于 目標型別,并且在轉換回原型別時將產生原值。 原始型別,或者
所以在這個串列初始化中
MyVector<float> foo{ size_t(3),2。 f }。
符合float型別的常量運算式size_t( 3 )被使用。
例如,如果在上面的演示程式中,你會寫
size_t n = 1。
A a1{ n, 1.0f }。
那么編譯器應該發出一個關于縮小轉換的訊息(至少MS VS 2019 C 編譯器會發出這樣的錯誤訊息)。
uj5u.com熱心網友回復:
來自cppreference on list initialisation.
串列初始化通過以下方式限制允許的隱式轉換 禁止以下內容:
.
...
從整數型別到浮點型別的轉換,除非源是一個常量運算式,其值可以精確地存盤在目標型別中。 準確地存盤在目標型別中
一般來說,串列初始化不會為你做隱式轉換。另外,因為 std::vector 有一個建構式 vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );,它就是被呼叫來構造vector的那個。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/310505.html
標籤:
下一篇:mysql和nginx安裝教程
