현대 C++를 배워야 하는 이유는 ROS에서 매우 광범위하게 사용되며 기본 프로그램을 배우지 않고는 이해할 수 없기 때문입니다.
예를 들어:
사실 설명이 정확하지 않습니다. ROS1/2에서 사용되는 포인터는 다음과 같습니다.
- std::shared_ptr
- 표준::고유_ptr
- 표준::weak_ptr
예:
virtual void
publish(std::unique_ptr<MessageT, MessageDeleter> & msg)
{
this->do_inter_process_publish(msg.get());
if (store_intra_process_message_) {
// Take the pointer from the unique_msg, release it and pass as a void *
// to the ipm. The ipm should then capture it again as a unique_ptr of
// the correct type.
// TODO(wjwwood):
// investigate how to transfer the custom deleter (if there is one)
// from the incoming unique_ptr through to the ipm's unique_ptr.
// See: http://stackoverflow.com/questions/11002641/dynamic-casting-for-unique-ptr
MessageT * msg_ptr = msg.get();
msg.release();
uint64_t message_seq =
store_intra_process_message_(intra_process_publisher_id_, msg_ptr, typeid(MessageT));
rcl_interfaces::msg::IntraProcessMessage ipm;
ipm.publisher_id = intra_process_publisher_id_;
ipm.message_sequence = message_seq;
auto status = rcl_publish(&intra_process_publisher_handle_, &ipm);
if (RCL_RET_PUBLISHER_INVALID == status) {
rcl_reset_error(); // next call will reset error message if not context
if (rcl_publisher_is_valid_except_context(&intra_process_publisher_handle_)) {
rcl_context_t * context = rcl_publisher_get_context(&intra_process_publisher_handle_);
if (nullptr != context && !rcl_context_is_valid(context)) {
// publisher is invalid due to context being shutdown
return;
}
}
}
if (RCL_RET_OK != status) {
rclcpp::exceptions::throw_from_rcl_error(status, "failed to publish intra process message");
}
} else {
// Always destroy the message, even if we don't consume it, for consistency.
msg.reset();
}
}
만큼 잘:
#include <memory>
void unique_func_ref(std::unique_ptr<int> & msg) {}
void unique_func_value(std::unique_ptr<int> msg) {}
int main(int argc, char ** argv)
{
std::unique_ptr<int> foo(new int);
std::unique_ptr<int> bar(new int);
unique_func_ref(foo);
// does not compile
// unique_func_value(bar);
unique_func_value(std::move(bar));
return 0;
}
현대 C++를 배우지 않고는 ROS1/2 로봇 프로그래밍은 문에 들어갈 수조차 없습니다...
C++로 첫 번째 hello world를 작성한지 24년이 지났지만 여전히 초보자입니다.
계속 배우려고 노력하십시오.
스마트 포인터는 C++11에 도입되었으므로 프로그래머는 더 이상 수동으로 메모리를 해제하는 데 신경 쓸 필요가 없습니다.
(기존 C++를 극복
new
하고delete
"수동 작업(메모리 누수를 잊을 수 없습니까?)"을 사용하여 리소스를 해제하십시오.)
#include <iostream>
#include <memory>
void foo(std::shared_ptr<int> i)
{
(*i)++;
}
int main()
{
// auto pointer = new int(10); // illegal, no direct assignment
// std::shared_ptr construction
auto pointer = std::make_shared<int>(10);
auto pointer2 = pointer; // reference count + 1
auto pointer3 = pointer; // reference count + 1
foo(pointer);
std::cout << *pointer << std::endl; // 11
int *p = pointer.get(); // does not increase reference count
std::cout << "pointer.use_count() = " << pointer.use_count() << std::endl;
std::cout << "pointer2.use_count() = " << pointer2.use_count() << std::endl;
std::cout << "pointer3.use_count() = " << pointer3.use_count() << std::endl;
pointer2.reset();
std::cout << "reset pointer2:" << std::endl;
std::cout << "pointer.use_count() = " << pointer.use_count() << std::endl;
std::cout << "pointer2.use_count() = " << pointer2.use_count() << std::endl;
std::cout << "pointer3.use_count() = " << pointer3.use_count() << std::endl;
pointer3.reset();
std::cout << "reset pointer3:" << std::endl;
std::cout << "pointer.use_count() = " << pointer.use_count() << std::endl;
std::cout << "pointer2.use_count() = " << pointer2.use_count() << std::endl;
std::cout << "pointer3.use_count() = " << pointer3.use_count() << std::endl;
// std::cout << *pointer << std::endl; // reference count equals 0, illegal access
// Before leaving the scope, the pointer is destructed and
// the reference count is reduced to 0
return 0;
}
#include <iostream>
#include <memory>
struct Foo {
Foo() { std::cout << "Foo::Foo" << std::endl; }
~Foo() { std::cout << "Foo::~Foo" << std::endl; }
void foo() { std::cout << "Foo::foo" << std::endl; }
};
void f(const Foo &) {
std::cout << "f(const Foo&)" << std::endl;
}
int main() {
std::unique_ptr<Foo> p1(std::make_unique<Foo>());
// p1 is not empty, prints
if (p1) p1->foo();
{
std::unique_ptr<Foo> p2(std::move(p1));
// p2 is not empty, prints
f(*p2);
// p2 is not empty, prints
if(p2) p2->foo();
// p1 is empty, no prints
if(p1) p1->foo();
p1 = std::move(p2);
// p2 is empty, no prints
if(p2) p2->foo();
std::cout << "p2 was destroyed" << std::endl;
}
// p1 is not empty, prints
if (p1) p1->foo();
// Foo instance will be destroyed when leaving the scope
}
#include <iostream>
#include <memory>
class A;
class B;
class A {
public:
std::shared_ptr<B> pointer;
~A() {
std::cout << "A was destroyed" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> pointer;
~B() {
std::cout << "B was destroyed" << std::endl;
}
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->pointer = b;
b->pointer = a;
return 0;
}