声明现有原始指针所有权的正确方法
Correct way to claim ownership of existing raw pointer
我有一些代码声明了一系列原始指针的所有权,我想知道是否有可接受的方法来做到这一点?我正在寻找的是一种在更大程度上强制执行代码所有权的方法。主要是,我一直在想我的构造函数是否应该直接采用唯一指针的向量。
作为旁注,一旦所有权被声明,数据就应该是不可变的。
代码大致遵循下面 class X
的模式。
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<int*> rawData)
: data { make_move_iterator(rawData.begin()), make_move_iterator(rawData.end()) }
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
vector<int*> rawData { new int(9) , new int(4) };
int* rawPointer = rawData[0];
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints garbage
return 0;
}
你犯了几个错误。
如果是const vector< unique_ptr<const int> >
数据;移动迭代器确实没有多大意义。原因是,int*
没有移动构造函数。
如果你用 vector < int* >
调用 X
的构造函数 X (vector<int*> rawData)
那么 vector < int* >
的复制构造函数就会被调用,但这不是你想要的想要。
顺便提一句。使用 move 的原因是为了避免大内存复制。例如 std::vector < int* >
:std::vector<int*>
的成员属性大小和指向存储 int*
的内存位置的指针也必须通过移动复制,而不是 int*s
自己。一个结论是,移动是为了主张所有权。
如果您想要这样的共享指针,请使用 std::shared_ptr
。它拥有一个计数器,它计算指向它自己的指针。
´
我的示例代码:
class X
{
public:
const std::vector< std::shared_ptr< const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (std::vector<std::shared_ptr<int>>& rawData)
//: data(rawData)
: data(rawData.cbegin(), rawData.cend())
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
std::vector<std::shared_ptr<int>> rawData { std::make_shared<int>(9), std::make_shared<int>(4) };
int* rawPointer = rawData[0].get();
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints not more garbage
return 0;
}
如果您不想使用 std::shared_ptr
,您将需要一个 GC。
如果不详细了解您的情况,很难post回答。但我的建议是一旦知道就将您的数据附加到 unique_ptr
。然后,您可以随意将 unique_ptr
移入和移出 vector
。例如:
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<unique_ptr<const int>>&& v)
: data { std::move(v) }
{ }
};
vector<unique_ptr<const int>>
collectRawData()
{
auto rawData = {9, 4};
vector<unique_ptr<const int>> data;
for (auto const& x : rawData)
data.push_back(make_unique<int>(x));
return data;
}
int main() {
auto rawData = collectRawData();
{ // New scope
X x(std::move(rawData));
cout << *(x.data[0]) << endl; // Unique pointer points to 9
cout << *(x.data[1]) << endl; // Unique pointer points to 4
}
}
我有一些代码声明了一系列原始指针的所有权,我想知道是否有可接受的方法来做到这一点?我正在寻找的是一种在更大程度上强制执行代码所有权的方法。主要是,我一直在想我的构造函数是否应该直接采用唯一指针的向量。
作为旁注,一旦所有权被声明,数据就应该是不可变的。
代码大致遵循下面 class X
的模式。
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<int*> rawData)
: data { make_move_iterator(rawData.begin()), make_move_iterator(rawData.end()) }
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
vector<int*> rawData { new int(9) , new int(4) };
int* rawPointer = rawData[0];
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints garbage
return 0;
}
你犯了几个错误。
如果是
const vector< unique_ptr<const int> >
数据;移动迭代器确实没有多大意义。原因是,int*
没有移动构造函数。如果你用
vector < int* >
调用X
的构造函数X (vector<int*> rawData)
那么vector < int* >
的复制构造函数就会被调用,但这不是你想要的想要。 顺便提一句。使用 move 的原因是为了避免大内存复制。例如std::vector < int* >
:std::vector<int*>
的成员属性大小和指向存储int*
的内存位置的指针也必须通过移动复制,而不是int*s
自己。一个结论是,移动是为了主张所有权。如果您想要这样的共享指针,请使用
std::shared_ptr
。它拥有一个计数器,它计算指向它自己的指针。
´ 我的示例代码:
class X
{
public:
const std::vector< std::shared_ptr< const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (std::vector<std::shared_ptr<int>>& rawData)
//: data(rawData)
: data(rawData.cbegin(), rawData.cend())
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
std::vector<std::shared_ptr<int>> rawData { std::make_shared<int>(9), std::make_shared<int>(4) };
int* rawPointer = rawData[0].get();
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints not more garbage
return 0;
}
如果您不想使用 std::shared_ptr
,您将需要一个 GC。
如果不详细了解您的情况,很难post回答。但我的建议是一旦知道就将您的数据附加到 unique_ptr
。然后,您可以随意将 unique_ptr
移入和移出 vector
。例如:
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<unique_ptr<const int>>&& v)
: data { std::move(v) }
{ }
};
vector<unique_ptr<const int>>
collectRawData()
{
auto rawData = {9, 4};
vector<unique_ptr<const int>> data;
for (auto const& x : rawData)
data.push_back(make_unique<int>(x));
return data;
}
int main() {
auto rawData = collectRawData();
{ // New scope
X x(std::move(rawData));
cout << *(x.data[0]) << endl; // Unique pointer points to 9
cout << *(x.data[1]) << endl; // Unique pointer points to 4
}
}