问题
I'm trying to make a clone of my C++ object, which is a wrapper around a C 'class'. I want to API to look like this:
LibrdfUri uri("http://uri.com"); 
LibrdfUri uri_clone = uri.clone(); // same value but points to different memory address
Here is my clone function
    ... 
    librdf_uri *LibrdfUri::get() const { // librdf_uri is the C type that I am wrapping 
        return librdf_uri_.get(); // librdf_uri_ is a unique pointer. .get returns the raw pointer
    }
    LibrdfUri LibrdfUri::clone() const {
        unsigned char * cstr =  librdf_uri_as_string(get()); // C library utility. Returns the value of the string
        int l = strlen((const char*)cstr);
        char *uri_string = new char[l+1];
        std::strcpy(uri_string, (const char*)cstr);
        return LibrdfUri((const char *) uri_string); //uri_string now contains the same characters as cstr
    }
But my test case still fails:
TEST_F(LibrdfUriTests, TestClone) {
    LibrdfUri uri("http://uri.com");
    LibrdfUri uri_clone = uri.clone();
    ASSERT_STREQ(uri.str().c_str(),
                 uri_clone.str().c_str()); // test passes
    ASSERT_NE(&uri, &uri_clone); // test passes
    ASSERT_NE(uri.get(), uri_clone.get()); // test fails, the addresses are the same. 
}
Can anybody see what is going on here?
Edit:
Here is the full class of LibrdfUri, in case its helpful.
    class LibrdfUri {
        struct deleter {
            void operator()(librdf_uri *ptr);
        };
        std::unique_ptr<librdf_uri, deleter> librdf_uri_;
    public:
        LibrdfUri() = default;
        [[nodiscard]] std::string str() const;
        explicit LibrdfUri(const std::string &uri);
        explicit LibrdfUri(librdf_uri *uri);
        [[nodiscard]] librdf_uri *get() const;
        LibrdfUri clone() const;
    };
   // implementation
    void LibrdfUri::deleter::operator()(librdf_uri *ptr) {
        librdf_free_uri(ptr);
    }
    LibrdfUri::LibrdfUri(const std::string &uri) {
        librdf_uri_ = std::unique_ptr<librdf_uri, deleter>(
                librdf_new_uri(World::getWorld(), (const unsigned char *) uri.c_str())
        );
    }
    std::string LibrdfUri::str() const {
        auto cstr = (unsigned char *) librdf_uri_as_string(get());
        std::string s = (const char *) cstr;
        return s;
    }
    librdf_uri *LibrdfUri::get() const {
        return librdf_uri_.get();
    }
    LibrdfUri::LibrdfUri(librdf_uri *uri)
            : librdf_uri_(std::unique_ptr<librdf_uri, deleter>(uri)) {}
Edit2
On a suggestion from a commenter I have changed my clone function to
    LibrdfUri LibrdfUri::clone() const {
        return LibrdfUri(librdf_new_uri_from_uri(get()));
    }
However the clone still doesnt behave as intended::
    LibrdfUri uri("http://uri.com");
    LibrdfUri uri_clone = uri.clone();
    std::cout << &uri << ", " << &uri_clone << std::endl;
    std::cout << uri.get() << ", " << uri_clone.get() << std::endl;
Outputs:
0x7ffc46e17400, 0x7ffc46e17408
0x55c0cf693120, 0x55c0cf693120
edit 3
Also, the output of
    LibrdfUri uri1("http://uri.com");
    LibrdfUri uri2("http://uri.com");
    std::cout << &uri1 << ", " << &uri2 << std::endl;
    std::cout << uri1.get() << ", " << uri2.get() << std::endl;
is
0x1fff000560, 0x1fff000568
0xed98a60, 0xed98a60
But the output of
    LibrdfUri uri1("http://uri1.com");
    LibrdfUri uri2("http://uri2.com");
    std::cout << &uri1 << ", " << &uri2 << std::endl;
    std::cout << uri1.get() << ", " << uri2.get() << std::endl;
is
0x7fff89c40120, 0x7fff89c40128
0x55a2e4c12120, 0x55a2e4c12470
来源:https://stackoverflow.com/questions/61992723/how-to-correctly-clone-a-string-from-a-struct-in-a-c-library-into-a-new-memory-a