All,std :: unique_ptr xóa chức năng, initializer_list - điều khiển phân bổ
Khi tôi khởi tạo một mảng các widget sử dụng định dạng initializer-list, một con trỏ thường trỏ đến một trường hợp phụ tùng thành viên biến biên dịch nhưng sau khi thay đổi std :: unique_ptr <> gcc cung cấp một lỗi biên dịch liên quan đến một hàm bị xóa.
$ uname -a
Linux .. 3.5.0-21-generiC# 32-Ubuntu SMP Tue ngày 11 tháng 12 18:51:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ g ++ - -version
g ++ (Ubuntu/Linaro 4.7.2-5ubuntu1) 4.7.2
mã này cung cấp cho các lỗi biên dịch sau:
#include <stdlib.h>
#include <memory>
class Widget
{
public:
Widget() {}
};
class W1 : public Widget
{
public:
W1() {}
};
class W2 : public Widget
{
public:
W2() {}
};
class WFactory
{
public:
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
~WFactory() { _w.reset(nullptr); }
// ~WFactory() { delete _w; } <--- for naked ptr
private:
// NOTE: does not compile
std::unique_ptr<Widget> _w;
// NOTE: does compile
// Widget* _w;
};
int main()
{
std::unique_ptr<Widget> a(new W1()); // <--- compiles fine
WFactory wf[] { 4, "msg" }; // <--- compiler error using unique_ptr<>
}
lỗi:
$ g++ -o unique_ptr -std=c++11 -Wall unique_ptr.cpp
unique_ptr.cpp: In function ‘int main()’:
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:22:7: note: ‘WFactory::WFactory(const WFactory&)’ is implicitly deleted because the default definition would be ill-formed:
unique_ptr.cpp:22:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Widget; _Dp = std::default_delete<Widget>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<Widget>]’
In file included from /usr/include/c++/4.7/memory:86:0,
from unique_ptr.cpp:2:
/usr/include/c++/4.7/bits/unique_ptr.h:262:7: error: declared here
unique_ptr.cpp:36:30: error: use of deleted function ‘WFactory::WFactory(const WFactory&)’
unique_ptr.cpp:36:14: warning: unused variable ‘wf’ [-Wunused-variable]
Tôi đang ở một mất mát như một trong hai: các cơ chế đằng sau hậu trường rằng sản lượng một fcxn xóa; hoặc đơn giản hơn, tại sao tính biểu cảm của std :: unique_ptr <> dường như bị hạn chế so với w/ptr trần truồng.
Câu hỏi của tôi là: lỗi
- thí điểm?
- lỗi trình biên dịch?
- tôi có thể lấy mã dự định để làm việc với một số thay đổi không?
Cảm ơn bạn.
Sửa 1
Dựa trên câu trả lời của bạn, mà tôi đánh giá cao, tôi có thể thực hiện thay đổi sau đây để WFactory:
(gắn cờ mã như vô đạo đức)
class WFactory
{
public:
WFactory(const WFactory& wf)
{
(const_cast<WFactory&>(wf)).moveto(_w);
}
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
~WFactory() { _w.reset(nullptr); }
void moveto(std::unique_ptr<Widget>& w)
{
w = std::move(_w);
}
private:
std::unique_ptr<Widget> _w;
};
và bây giờ chương trình biên dịch và chạy. Tôi đánh giá cao rằng các tiêu chuẩn folks đã viết các đặc điểm kỹ thuật cho một lý do, vì vậy tôi đăng kết quả của tôi như là một chuyên môn tốt đức tin cho trường hợp của tôi ở bàn tay, nơi tôi thực sự muốn nhấn mạnh sự độc đáo của ptr.
Chỉnh sửa 2
Dựa trên trả lời của Jonathan, đoạn code sau không ngăn chặn di chuyển ctor ngầm:
class WFactory
{
public:
WFactory(const int i) : _w(new W1()) {}
WFactory(const char* s) : _w(new W2()) {}
private:
std::unique_ptr<Widget> _w;
};
Lưu ý rằng không có ~WFactory() {..}
ở tất cả.
Có lẽ có ya-ans, nhưng tôi đã thấy rằng việc sử dụng lặp lại kiểu C++ 11 trên wf [] trong Main() sẽ trả về lỗi no-copy-ctor-for-WFactory.Đó là:
int Main()
..
WFactory wf[] { 4, "msg" };
for (WFactory iwf : wf) <---- compiler error again
// ..
for (unsigned i = 0; i < 2; ++i) <--- gcc happy
wf[i] // ..
}
Tôi đoán đó là hiển nhiên rằng C++ 11 kiểu lặp mới được làm một bản sao đối tượng.
Việc khởi tạo qua danh sách được sắp xếp yêu cầu các đối tượng được sao chép chính thức, thật không may. –
Cảm ơn bạn, điều đó thật thú vị. Bản sao ở đâu? Lỗi chỉ ra rằng WFactory phải được sao chép. Tôi không hiểu. – JayInNyc
Đó là thông số kỹ thuật của ngôn ngữ. Bản sao sẽ không thực sự xảy ra trong thực tế, nhưng lớp vẫn cần phải có một hàm tạo bản sao có thể truy cập. –