foo.h中
#include <iostream>
#include <memory>
class Bar
{
public:
Bar() {};
~Bar() {};
void print() {
std::cout << "hello";
}
};
class Foo
{
public:
Foo();
~Foo();
void use() {
pteste->print();
}
private:
std::unique_ptr<Bar> pteste;
};
#endif
的main.cpp
#include <memory>
#include "foo.h"
int main(int argc, char *argv[])
{
Foo s;
s.use();
return 0;
}
为什么以及如何“正常”工作?
由于
编辑:我理解不完整的类型,但是当我可以使用unique_ptr而不使用new时会发生什么呢?EDIT2:为我的问题更好地组织代码
答案 0 :(得分:3)
简短的回答:它不起作用。
这个reference表示std::unique_ptr
的默认构造函数创建一个空的唯一指针,这意味着它没有关联的对象。
此代码打印hello
的原因是因为此声明
std::cout << "hello";
不需要任何Bar
。它也可以是静态方法。也许编译器内联函数并用s.use()
语句替换std::cout
。但即使它确实调用了该方法,您也不会注意到任何错误,因为它根本不会访问Bar
的内存。
对你的班级做一点改动,你会看到我的意思:
class Bar
{
public:
Bar() : data(10) {};
~Bar() {};
void print() {
std::cout << "hello, data is: " << data;
}
int data;
};
现在,print
访问无效内存,因为您从未调用new
(甚至更好:make_unique
)。它甚至可以工作并向控制台打印一些内容,但data
的输出将是垃圾。如果你很幸运,应用程序将崩溃。
它似乎有效的另一个原因(感谢Stas):
std::unique_ptr
定义operator->
,它只返回包含的指针,但不检查指针是否指向有效内存。所以pteste->
不会抛出异常。
答案 1 :(得分:1)
是的,此代码将“正常”向控制台打印“hello”,它与unique_ptr
无关。您可以将std::unique_ptr<Bar> pteste
替换为Bar* pteste
中的Bar
并获得相同的结果。
考虑如何调用pteste->print()
。
您可以将Bar::print()
视为一个指向Bar
对象的自由函数:
void print(Bar* this) {
std::cout << "hello";
}
请注意,传递给print(Bar*)
的指针永远不会被触及,所以理论上你可以传递任何你想要的东西(null,垃圾等),它会打印出“hello”到控制台。
答案 2 :(得分:0)
这是因为
std::unique_ptr<Bar> pteste;
是实例的指针声明,它不实例化指针,因此此时不需要知道有关Bar的详细信息(例如ctor)。
在
的情况下Bar pteste
为了构造pteste,它需要知道定义,但由于Bar只是向前声明,因此会产生错误。
答案 3 :(得分:0)
所有指针都以相同的方式实现。即使你有指向不同类型的指针,通常都是int的大小。因此编译器在编译代码时不需要知道指针的类型。现在,如果你要取消引用那个将成为另一个故事的指针。即使您要初始化unique_ptr
,也需要知道类型,因为new
需要查看构造函数。