2017-12-01 26 views
0

나는 이동과 lvalue 의미론에있어서 꽤 새로운 것이다. 그리고 내가 잘못하고 있다는 인상을받습니다. 여기 한번 FunctContainer을 쓸 수 있기를 원하는 코드가 구현됩니다 fc1에 저장된 함수의 수명이 f의 하나는 수명이되도록lvalue를 참조하고 rvalue 인 경우 복사본을 만듭니다. 즉 rvalue를 영구화합니다.

std::function<double(double)> f = [](double x){return (x * x - 1); }; 

FunctContainer fc1 = FunctContainer(f); 

FunctContainer fc2 = FunctContainer([](double x){return (x * x - 1); }); 

내가 FunctContainer 년대의 ctors을 작성하려면 포함 된 기능의 fc2fc2 자체의 수명입니다.

나는 (아래 참조) 필자는 정말로 만족스럽지 않지만 (나는 잘못 알고있다).

이것은 올바른 C++이지만 잘못된 동작입니다. f_이 rvalue 일 때 생성자를 호출 한 후 f_이 만료됩니다.

class FunctContainerWRONG{ 
public: 
    IntegrandNotProjecting(const std::function<double(double)>& function) 
    : f_(function){} 
    IntegrandNotProjecting(const std::function<double(double)>&& function) 
    : f_(std::move(function)){} 
    const std::function<double(double)>& f_; 
private: 
}; 

이 나 한테 끔찍한 외모와 아마 올바른 C하지 ++하지만 원하는 동작이 어떻게 생겼는지 의사에 설명하기위한 것입니다. 나는 새로운 객체를 constuct을 피하려고하고 난 그냥 내 객체를하게 할 수있는 경우 "계속"

class FunctContainer{ 
public: 
    FunctContainer(const std::function<double(double)>& function) 
    : f_p(nullptr), 
     f_(function){} 
    FunctContainer(const std::function<double(double)>&& function) 
    : f_p()std::make_shared<std::function<double(double)>>(function)), 
     f_(*f_p){} 
private: 
    std::shared_ptr<std::function<double(double)>> f_p; 
    const std::function<double(double)>& f_; 
}; 
+0

그래서 (일관성 소유권 및 수명 관리 이외의) 마지막 예와 실제로 어떤 문제가 있는지? 소유권은 어쨌든 공유되지 않기 때문에 'unique_ptr'을 사용할 수 있습니다. – VTT

+0

@VTT 마지막 예제에서 싫어하는 것은 함수가 rvalue 인 경우 복사본을 만들고 싶지만 컴파일러가이를 최적화하도록 명시 적으로 선호하는 것입니다. 또한, 만약 당신이 rvalue 있고 다른 경우에 공유 포인터가 고유해야합니다. 이것은 하나 이상의 포인터가 필요하다는 것을 의미하며이 포인터를 관리합니다. – jimifiki

답변

1

전달 참조하고 쉽게를 달성 할 수 있습니다 규칙을 무너 참조.

  • 당신이 좌변makeFunctContainer를 호출

    template <typename T> 
    struct FunctContainer 
    { 
        T _f; 
    
        template <typename TFwd> 
        FunctContainer(TFwd&& f) : _f{std::forward<TFwd>(f)} { } 
    }; 
    
    template <typename T> 
    auto makeFunctContainer(T&& f) -> FunctContainer<T> 
    { 
        return {std::forward<T>(f)}; 
    } 
    

    , T좌변 참조 될 것입니다. 즉, 왼쪽 값FucntContainer 안에 저장합니다. 당신이 를 rvaluemakeFunctContainer를 호출하면

  • T 될 것입니다. 즉, FucntContainer 안에 저장합니다.


사용 예제 :

auto fc0 = makeFunctContainer(std::move(f0)); // `fc0` owns `f0` 
auto fc1 = makeFunctContainer(f1); // `fc1` stores a reference to `f1`