当使用静态constexpr成员构造时,为什么std :: make_shared与new不同?

时间:2017-04-19 03:07:59

标签: c++ c++11 constexpr make-shared

#include <iostream>
#include <vector>
#include <memory>

class Node{
public:
    static constexpr int data_size = sizeof(int);
};

class View{
public:
    View(int size){
    }
};

class Header: public Node{
public:
    void foo(){
        std::shared_ptr<View> v = std::make_shared<View>(data_size);
    }

    void bar(){
        std::shared_ptr<View> v(new View(data_size));
    }
    View bar1(){
        return View(data_size);
    }
    void bar2(){
        View *v = new View(data_size);
    }
    int bar3(){
        return data_size;
    }
};

int main() {

    Header *h = new Header();

    // This 1 lines below will produce the error
    h->foo();

    // These 4 lines are ok
    h->bar();
    h->bar1();
    h->bar2();
    h->bar3();

    return 0;
}

调用foo()时,会出现以下错误:

/Applications/CLion.app/Contents/bin/cmake/bin/cmake --build /Users/everettjf/code/cpptest/cmake-build-debug --target all -- -j 8
Scanning dependencies of target cpptest
[ 50%] Building CXX object CMakeFiles/cpptest.dir/main.cpp.o
[100%] Linking CXX executable cpptest
Undefined symbols for architecture x86_64:
  "Node::data_size", referenced from:
      Header::foo() in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [cpptest] Error 1
make[1]: *** [CMakeFiles/cpptest.dir/all] Error 2
make: *** [all] Error 2

当我使用new来初始化shared_ptr时,没关系。但是当我使用make_shared时,会发生链接错误。

为什么std :: make_shared在使用静态constexpr成员构造时与new不同?

我的环境是使用Clion的macOS,CMakeList.txt是:

cmake_minimum_required(VERSION 3.6)
project(cpptest)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(cpptest ${SOURCE_FILES})

1 个答案:

答案 0 :(得分:0)

为什么新工作正在进行..

std::shared_ptr<View> v(new View(data_size));

在上面的代码中(我的猜测是),编译器用值本身替换data_size。所以它编译并运行良好。

为什么std :: make_shared&lt;&gt;()失败..

std::shared_ptr<View> v = std::make_shared<View>(data_size);

std :: make_shared执行称为完美转发的操作。在上面的例子中,它需要知道Node :: data_size的地址。由于您没有在任何地方定义它,链接器无法找到符号并抛出错误。

要解决此问题,请在代码中定义符号Node :: data_size。