Mục đích của là std::make_pair
gì?
Tại sao không làm std::pair<int, char>(0, 'a')
?
Có sự khác biệt nào giữa hai phương pháp không?
std::make_pair
là dự phòng. Có một câu trả lời dưới đây chi tiết này.
Mục đích của là std::make_pair
gì?
Tại sao không làm std::pair<int, char>(0, 'a')
?
Có sự khác biệt nào giữa hai phương pháp không?
std::make_pair
là dự phòng. Có một câu trả lời dưới đây chi tiết này.
Câu trả lời:
Sự khác biệt là với std::pair
bạn cần chỉ định các loại của cả hai phần tử, trong khi đó std::make_pair
sẽ tạo một cặp với loại phần tử được truyền cho nó, mà bạn không cần phải nói với nó. Đó là những gì tôi có thể thu thập từ nhiều tài liệu khác nhau.
Xem ví dụ này từ http://www.cplusplus.com/reference/std/utility/make_ Pair /
pair <int,int> one;
pair <int,int> two;
one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>
Ngoài phần thưởng chuyển đổi ngầm định của nó, nếu bạn không sử dụng make_ Pair bạn phải làm
one = pair<int,int>(10,20)
mỗi lần bạn được chỉ định cho một người, điều đó sẽ gây phiền nhiễu theo thời gian ...
std::make_pair
. Rõ ràng nó chỉ để thuận tiện.
one = {10, 20}
hôm nay nhưng tôi không có trình biên dịch C ++ 11 để kiểm tra.
make_pair
hoạt động với các loại chưa được đặt tên, bao gồm các cấu trúc, đoàn thể, lambdas và hình tượng trưng khác.
Như @MSalters đã trả lời ở trên, bây giờ bạn có thể sử dụng dấu ngoặc nhọn để thực hiện điều này trong C ++ 11 (chỉ cần xác minh điều này với trình biên dịch C ++ 11):
pair<int, int> p = {1, 2};
Các đối số khuôn mẫu lớp không thể được suy ra từ hàm tạo trước C ++ 17
Trước C ++ 17, bạn không thể viết một cái gì đó như:
std::pair p(1, 'a');
vì điều đó sẽ suy ra các kiểu mẫu từ các đối số của hàm tạo.
C ++ 17 làm cho cú pháp đó có thể, và do đó make_pair
dư thừa.
Trước C ++ 17, std::make_pair
cho phép chúng tôi viết mã dài ít hơn:
MyLongClassName1 o1;
MyLongClassName2 o2;
auto p = std::make_pair(o1, o2);
thay vì dài dòng hơn:
std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};
mà lặp đi lặp lại các loại, và có thể rất dài.
Kiểu suy luận hoạt động trong trường hợp tiền C ++ 17 đó vì make_pair
không phải là hàm tạo.
make_pair
về cơ bản là tương đương với:
template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
return std::pair<T1, T2>(t1, t2);
}
Khái niệm tương tự áp dụng cho inserter
vs insert_iterator
.
Xem thêm:
Ví dụ tối thiểu
Để làm cho mọi thứ cụ thể hơn, chúng ta có thể quan sát vấn đề tối thiểu với:
main.cpp
template <class MyType>
struct MyClass {
MyType i;
MyClass(MyType i) : i(i) {}
};
template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
return MyClass<MyType>(i);
}
int main() {
MyClass<int> my_class(1);
}
sau đó:
g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp
vui vẻ biên dịch, nhưng:
g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp
thất bại với:
main.cpp: In function ‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’
MyClass my_class(1);
^~~~~~~~
và yêu cầu thay vì làm việc:
MyClass<int> my_class(1);
hoặc người trợ giúp:
auto my_class = make_my_class(1);
trong đó sử dụng một hàm thông thường thay vì một hàm tạo.
Sự khác biệt cho `std :: Reference_wrapper
Nhận xét này đề cập đến việc std::make_pair
hủy bỏ std::reference_wrapper
trong khi nhà xây dựng thì không, vì vậy đó là một điểm khác biệt. Ví dụ TODO.
Đã thử nghiệm với GCC 8.1.0, Ubuntu 16.04 .
std::make_pair
không bị phản đối trong C ++ 17?
make_pair
hủy đóng gói tham chiếu, vì vậy nó thực sự khác với CTAD.
Không có sự khác biệt giữa việc sử dụng make_pair
và gọi rõ ràng hàm pair
tạo với các đối số kiểu đã chỉ định. std::make_pair
sẽ thuận tiện hơn khi các kiểu dài dòng vì một phương thức mẫu có loại trừ dựa trên các tham số đã cho. Ví dụ,
std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;
// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));
// longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));
Điều đáng chú ý là đây là một thành ngữ phổ biến trong lập trình mẫu C ++. Nó được gọi là thành ngữ Object Generator, bạn có thể tìm thêm thông tin và một ví dụ hay ở đây .
Chỉnh sửa Như ai đó đã đề xuất trong các nhận xét (kể từ khi xóa), phần sau đây là một trích xuất được sửa đổi một chút từ liên kết trong trường hợp nó bị hỏng.
Trình tạo đối tượng cho phép tạo các đối tượng mà không chỉ định rõ ràng các loại của chúng. Nó dựa trên một thuộc tính hữu ích của các mẫu hàm mà các mẫu lớp không có: Các tham số loại của mẫu hàm được tự động suy ra từ các tham số thực tế của nó. std::make_pair
là một ví dụ đơn giản trả về một thể hiện của std::pair
mẫu tùy thuộc vào các tham số thực tế của std::make_pair
hàm.
template <class T, class U>
std::pair <T, U>
make_pair(T t, U u)
{
return std::pair <T, U> (t,u);
}
&&
từ C ++ 11.
make_ Pair tạo một bản sao bổ sung trên hàm tạo trực tiếp. Tôi luôn gõ các cặp của mình để cung cấp cú pháp đơn giản.
Điều này cho thấy sự khác biệt (ví dụ của Rampal Chaudhary):
class Sample
{
static int _noOfObjects;
int _objectNo;
public:
Sample() :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
}
Sample( const Sample& sample) :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
}
~Sample()
{
std::cout<<"Destroying object "<<_objectNo<<std::endl;
}
};
int Sample::_noOfObjects = 0;
int main(int argc, char* argv[])
{
Sample sample;
std::map<int,Sample> map;
map.insert( std::make_pair( 1, sample) );
//map.insert( std::pair<int,Sample>( 1, sample) );
return 0;
}
std::move
chỉ bên trong insert
và / hoặc xung quanh những gì sẽ là một tài liệu tham khảo sample
. Nó chỉ là khi tôi thay đổi std::map<int,Sample>
để std::map<int,Sample const&>
mà tôi giảm số lượng các đối tượng được xây dựng, và chỉ khi tôi xóa các constructor sao chép mà tôi loại bỏ tất cả các bản sao (rõ ràng). Sau khi thực hiện cả hai thay đổi đó, kết quả của tôi bao gồm một cuộc gọi đến hàm tạo mặc định và hai cuộc gọi đến hàm hủy cho cùng một đối tượng. Tôi nghĩ rằng tôi phải thiếu một cái gì đó. (g ++ 5.4.1, c ++ 11)
emplace
thay vì insert
nếu bạn chỉ xây dựng một giá trị để chèn ngay lập tức (và bạn không muốn có thêm trường hợp.) Đó không phải là lĩnh vực chuyên môn của tôi, nếu tôi thậm chí có thể nói tôi có một, nhưng sao chép / di chuyển ngữ nghĩa được giới thiệu bởi C ++ 11 đã giúp tôi rất nhiều.
bắt đầu từ c ++ 11 chỉ cần sử dụng khởi tạo thống nhất cho các cặp. Vì vậy, thay vì:
std::make_pair(1, 2);
hoặc là
std::pair<int, int>(1, 2);
chỉ dùng
{1, 2};
{1, 2}
có thể được sử dụng để khởi tạo một cặp, nhưng không cam kết cho loại cặp. Tức là khi sử dụng tự động, bạn phải cam kết với một loại trên RHS : auto p = std::pair{"Tokyo"s, 9.00};
.